<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>文本多模态感知分析报告</title>
    <style>
        body {
            font-family: "Segoe UI", "Microsoft YaHei", sans-serif;
            line-height: 1.6;
            color: #333;
            max-width: 1000px;
            margin: 0 auto;
            padding: 20px;
            background: #fff;
        }
        .section {
            margin-bottom: 30px;
            padding: 15px;
            border-left: 4px solid #007bff;
            background: #f8f9fa;
        }
        .subsection {
            margin-top: 15px;
            padding: 10px;
            background: #ffffff;
            border-radius: 4px;
            box-shadow: 0 1px 3px rgba(0,0,0,0.05);
        }
        h2 {
            color: #007bff;
            border-bottom: 1px solid #eee;
            padding-bottom: 8px;
        }
        h3 {
            color: #495057;
            margin-top: 20px;
        }
        ul, ol {
            padding-left: 20px;
            margin: 8px 0;
        }
        li {
            margin-bottom: 4px;
        }
        .field-label {
            font-weight: bold;
            color: #495057;
        }
        .empty-section {
            color: #6c757d;
            font-style: italic;
        }

        /* Share buttons */
        .share-options {
            margin: 30px 0;
            padding: 15px;
            background: #e9ecef;
            border-radius: 8px;
            text-align: center;
        }
        .share-btn {
            margin: 5px 8px;
            padding: 8px 16px;
            background: #007bff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
        }
        .share-btn:hover {
            background: #0056b3;
        }
        .details-block {
            margin-top: 12px;
            border-left: 2px solid #e0e0e0;
            padding-left: 12px;
        }
        .details-block summary {
            cursor: pointer;
            color: #1a73e8;
            font-weight: 500;
        }
        .details-content {
            margin-top: 8px;
            padding: 8px 0;
            border-top: 1px dashed #ddd;
        }
        code {
            background: #f5f5f5;
            padding: 2px 4px;
            border-radius: 3px;
            font-family: monospace;
        }
        .suggestion-section {
          background-color: #f8f9fa;
          border-left: 4px solid #0d6efd;
          padding: 16px;
          margin: 24px 0;
        }
        .suggestion-content {
          white-space: pre-wrap;
          line-height: 1.6;
        }
        .suggestion-error {
          color: #dc3545;
          font-style: italic;
        }
        /* 打印时隐藏分享操作按钮 */
        @media print {
          #btn-export-md,
          #btn-generate-pdf,
          #btn-copy-text,
          .share-options > h3 {
            display: none !important;
          }
          #scroll-controls {
            display: none !important;
            visibility: hidden !important;
            height: 0 !important;
            overflow: hidden !important;
          }
        }
        .watermark-grid {
            position: fixed;
            top: 0;
            left: 0;
            width: 100vw;
            height: 100vh;
            z-index: 9999;
            pointer-events: none;        /* 点击穿透 */
            user-select: none;           /* 禁止选中 */
            display: grid;
            grid-template-columns: repeat(5, 1fr);  /* 5列 */
            grid-template-rows: repeat(8, 1fr);     /* 8行，避免太密 */
            opacity: 0.12;               /* 从 0.05 提高到 0.12，清晰但不刺眼 */
            transform: rotate(-30deg);
            font-weight: bold;
            font-family: "Microsoft YaHei", sans-serif;
        }

        .watermark-grid span {
            padding: 30px;               /* 内边距加大，避免文字紧贴 */
            font-size: 48px;             /* 放大三倍！关键改动 */
            color: rgba(54, 52, 52, 0.9); /* 红色用 rgba 控制，保留透明通道 */
            font-weight: bold;
            white-space: nowrap;         /* 防止换行 */
            text-align: center;
            text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.3); /* 轻微阴影，提升可读性 */
        }
    </style>
</head>
<body>
    <div class="watermark-grid">
        <span>内部审计</span><span>严禁外传</span><span>内部审计</span><span>严禁外传</span>
        <!-- 更多... -->
    </div>

    <!-- 报告内容 -->
    <div class="report">
        {% if data%}
        <h2>{{ data.meta.title or '文本多模态感知分析报告' }}</h2>
        {% endif %}

        <!-- 分析元信息 -->
        {% if data%}
        <div class="section">
          <h3>分析元信息</h3>
          <div class="subsection">
            <!-- 基础标识 -->
            <p><span class="field-label">报告ID：</span>{{ data.id or '未知' }}</p>
            {% if data.formatter_time %}
              <p><span class="field-label">生成时间：</span>{{ data.formatter_time | default('未知') }}</p>
            {% endif %}
            <p><span class="field-label">报告类型：</span>{{ data.type or '未指定' }}</p>

            <!-- 原始内容（建议用 <pre> 或限制高度） -->
            {% if data.source and data.source.content %}
              <p><span class="field-label">原始文本：</span></p>
              <div style="background:#f9f9f9; padding:8px; border-radius:4px; max-height:150px; overflow:auto; font-family:monospace; font-size:0.9em;">
                {{ data.source.content | e }}
              </div>
            {% endif %}

            <!-- AI 与模型信息 -->
            <p><span class="field-label">AI 生成：</span>{{ '是' if data.meta.created_by_ai else '否' }}</p>
            <p><span class="field-label">模型版本：</span>{{ data.meta.llm_model or '未知' }}</p>
            <p><span class="field-label">库版本：</span>{{ data.meta.library_version or '未知' }}</p>
<!--            <p><span class="field-label">叙事增强：</span>{{ '已启用' if data.meta.narrative_enriched else '未启用' }}</p>-->

            <!-- 后续注入字段 -->
            {% if data.meta.validity_level %}
              <p><span class="field-label">有效性等级：</span>{{ data.meta.validity_level }}</p>
            {% endif %}
            {% if data.meta.privacy_scope and data.meta.privacy_scope.privacy_level is defined %}
              <p><span class="field-label">隐私等级：</span>{{ "%.2f"|format(data.meta.privacy_scope.privacy_level) }}</p>
            {% endif %}
          </div>
        </div>
        {% endif %}

        <!-- 1. 源数据提取（参与者） -->
        {% if data.get('participants') %}
        <div class="section">
            <h3>1. 参与者信息</h3>
            <details class="details-block">
                <summary>🔍 展开参与者解析详情</summary>
                <div class="subsection" style="margin-top: 16px;">
                    {% for p in data.participants %}
                    <div style="margin-bottom: 24px; padding: 12px; border-left: 2px solid #4a90e2; background: #f9fbfd;">
                        <!-- 核心标识 -->
                        <p><span class="field-label">原始指称：</span><code>{{ p.entity }}</code></p>

                        <!-- 身份与社会属性（仅当任一字段存在时显示） -->
                        {% set has_identity = [
                            p.get('occupation'),
                            p.get('social_role'),
                            p.get('family_status'),
                            p.get('institutional_affiliation'),
                            p.get('education_level'),
                            p.get('primary_language'),
                            p.get('cultural_identity'),
                            p.get('beliefs_or_values')
                        ] | select | list %}
                        {% if has_identity %}
                        <details class="details-block" style="margin-top: 8px;">
                            <summary>🧾 身份与社会属性</summary>
                            <div style="margin-top: 6px; padding-left: 12px; border-left: 1px dashed #ccc;">
                                {% if p.get('occupation') %}<p><span class="field-label">职业身份：</span>{{ p.occupation }}</p>{% endif %}
                                {% if p.get('social_role') %}<p><span class="field-label">社会关系角色：</span>{{ p.social_role }}</p>{% endif %}
                                {% if p.get('family_status') %}<p><span class="field-label">家庭状态：</span>{{ p.family_status }}</p>{% endif %}
                                {% if p.get('institutional_affiliation') %}<p><span class="field-label">所属机构：</span>{{ p.institutional_affiliation | join(', ') }}</p>{% endif %}
                                {% if p.get('education_level') %}<p><span class="field-label">教育程度：</span>{{ p.education_level }}</p>{% endif %}
                                {% if p.get('primary_language') %}<p><span class="field-label">主要使用语言：</span>{{ p.primary_language }}</p>{% endif %}
                                {% if p.get('cultural_identity') %}<p><span class="field-label">文化/族群认同：</span>{{ p.cultural_identity | join(', ') }}</p>{% endif %}
                                {% if p.get('beliefs_or_values') %}<p><span class="field-label">明确陈述的信念或价值观：</span>{{ p.beliefs_or_values }}</p>{% endif %}
                            </div>
                        </details>
                        {% endif %}

                        <!-- 生物与生理特征（仅当任一字段存在时显示） -->
                        {% set has_bio = [
                            p.get('gender'),
                            p.get('age_range'),
                            p.get('ethnicity_or_origin'),
                            p.get('physical_traits')
                        ] | select | list %}
                        {% if has_bio %}
                        <details class="details-block" style="margin-top: 8px;">
                            <summary>🧬 生物与生理特征</summary>
                            <div style="margin-top: 6px; padding-left: 12px; border-left: 1px dashed #ccc;">
                                {% if p.get('gender') %}<p><span class="field-label">性别标识：</span>{{ p.gender }}</p>{% endif %}
                                {% if p.get('age_range') %}<p><span class="field-label">年龄阶段：</span>{{ p.age_range }}</p>{% endif %}
                                {% if p.get('ethnicity_or_origin') %}<p><span class="field-label">地域或族群来源：</span>{{ p.ethnicity_or_origin }}</p>{% endif %}
                                {% if p.get('physical_traits') %}<p><span class="field-label">长期生理特征：</span>{{ p.physical_traits | join(', ') }}</p>{% endif %}
                            </div>
                        </details>
                        {% endif %}

                        <!-- 当前外显状态（仅当任一字段存在时显示） -->
                        {% set has_state = [
                            p.get('appearance'),
                            p.get('current_physical_state'),
                            p.get('visible_injury_or_wound'),
                            p.get('carried_objects'),
                            p.get('worn_technology'),
                            p.get('inherent_odor'),
                            p.get('voice_quality'),
                            p.get('speech_pattern')
                        ] | select | list %}
                        {% if has_state %}
                        <details class="details-block" style="margin-top: 8px;">
                            <summary>👁️ 当前外显状态</summary>
                            <div style="margin-top: 6px; padding-left: 12px; border-left: 1px dashed #ccc;">
                                {% if p.get('appearance') %}<p><span class="field-label">外显特征：</span>{{ p.appearance | join(', ') }}</p>{% endif %}
                                {% if p.get('current_physical_state') %}<p><span class="field-label">当前身体/情绪状态：</span>{{ p.current_physical_state }}</p>{% endif %}
                                {% if p.get('visible_injury_or_wound') %}<p><span class="field-label">可见伤痕或医疗痕迹：</span>{{ p.visible_injury_or_wound | join(', ') }}</p>{% endif %}
                                {% if p.get('carried_objects') %}<p><span class="field-label">持有物品：</span>{{ p.carried_objects | join(', ') }}</p>{% endif %}
                                {% if p.get('worn_technology') %}<p><span class="field-label">佩戴的电子设备：</span>{{ p.worn_technology | join(', ') }}</p>{% endif %}
                                {% if p.get('inherent_odor') %}<p><span class="field-label">相关气味：</span>{{ p.inherent_odor | join(', ') }}</p>{% endif %}
                                {% if p.get('voice_quality') %}<p><span class="field-label">嗓音特征：</span>{{ p.voice_quality }}</p>{% endif %}
                                {% if p.get('speech_pattern') %}<p><span class="field-label">言语模式：</span>{{ p.speech_pattern }}</p>{% endif %}
                            </div>
                        </details>
                        {% endif %}

                        <!-- 心理与行为倾向（仅当任一字段存在时显示） -->
                        {% set has_psych = [
                            p.get('personality_traits'),
                            p.get('behavioral_tendencies')
                        ] | select | list %}
                        {% if has_psych %}
                        <details class="details-block" style="margin-top: 8px;">
                            <summary>🧠 心理与行为倾向</summary>
                            <div style="margin-top: 6px; padding-left: 12px; border-left: 1px dashed #ccc;">
                                {% if p.get('personality_traits') %}<p><span class="field-label">人格特质陈述：</span>{{ p.personality_traits | join(', ') }}</p>{% endif %}
                                {% if p.get('behavioral_tendencies') %}<p><span class="field-label">习惯性行为：</span>{{ p.behavioral_tendencies | join(', ') }}</p>{% endif %}
                            </div>
                        </details>
                        {% endif %}

                        <!-- 事件中的功能角色（高亮显示） -->
                        {% if p.get('interaction_role') %}
                        <p style="margin-top: 12px; padding: 8px; background-color: #fff8e1; border-radius: 4px;">
                            <span class="field-label">📌 事件功能角色：</span>{{ p.interaction_role }}
                        </p>
                        {% endif %}
                    </div>
                    {% endfor %}
                </div>
            </details>
        </div>
        {% endif %}

        <!-- 2. 时间感知 -->
        {% if data.get('temporal') %}
        <div class="section">
            <h3>2. 时间感知</h3>
            <div class="subsection">
                <!-- 主摘要（始终显示） -->
                {% if data.temporal.get('summary') %}
                <p><span class="field-label">时间摘要：</span>{{ data.temporal.summary }}</p>
                {% endif %}

                <!-- 折叠详情 -->
                <details class="details-block">
                    <summary>🔍 展开时间解析详情（含全局证据、语义标识与事件细节）</summary>
                    <div class="details-content">

                        <!-- 全局原文证据（始终显示，带说明） -->
                        {% if data.temporal.get('evidence') %}
                        <p>
                            <span class="field-label">全局原文证据：</span>
                            <small style="color: #666; font-style: italic;">（支撑整个时间判断的原始文本片段）</small><br>
                            {% for frag in data.temporal.evidence %}
                            <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                            {% endfor %}
                        </p>
                        {% endif %}

                        <!-- 时间事件列表 -->
                        {% if data.temporal.get('events') and data.temporal.events %}
                        <h4 style="margin-top: 16px; margin-bottom: 10px;">时间事件详情（共 {{ data.temporal.events | length }} 项）</h4>
                        {% for ev in data.temporal.events %}
                        <div class="relation-item" style="padding: 10px; background: #f9f9f9; border-radius: 6px; margin-bottom: 12px;">

                            <!-- 核心时间信息 -->
                            {% if ev.get('semantic_notation') %}<p><span class="field-label">语义标识：</span><code>{{ ev.semantic_notation }}</code></p>{% endif %}
                            {% if ev.get('experiencer') %}<p><span class="field-label">陈述主体：</span>{{ ev.experiencer }}</p>{% endif %}
                            {% if ev.get('exact_literals') %}<p><span class="field-label">精确时间：</span>{{ ev.exact_literals | join(', ') }}</p>{% endif %}
                            {% if ev.get('time_ranges') %}<p><span class="field-label">时间区间：</span>{{ ev.time_ranges | join('; ') }}</p>{% endif %}
                            {% if ev.get('durations') %}<p><span class="field-label">持续时长：</span>{{ ev.durations | join(', ') }}</p>{% endif %}
                            {% if ev.get('frequencies') %}<p><span class="field-label">频率/周期性：</span>{{ ev.frequencies | join(', ') }}</p>{% endif %}
                            {% if ev.get('seasonal_or_cultural_time') %}<p><span class="field-label">节令/文化时间：</span>{{ ev.seasonal_or_cultural_time | join(', ') }}</p>{% endif %}
                            {% if ev.get('temporal_anchor') %}<p><span class="field-label">时间参考锚点：</span>{{ ev.temporal_anchor }}</p>{% endif %}

                            <!-- 模糊与否定表达 -->
                            {% if ev.get('relative_expressions') or ev.get('negated_time') or ev.get('uncertainty_modifiers') %}
                            {% if ev.get('relative_expressions') %}<p><span class="field-label">相对/模糊时间：</span>{{ ev.relative_expressions | join(', ') }}</p>{% endif %}
                            {% if ev.get('negated_time') %}<p><span class="field-label">被否定的时间：</span>{{ ev.negated_time | join(', ') }}</p>{% endif %}
                            {% if ev.get('uncertainty_modifiers') %}<p><span class="field-label">不确定性修饰语：</span>{{ ev.uncertainty_modifiers | join(', ') }}</p>{% endif %}
                            {% endif %}

                            <!-- 语言与上下文线索 -->
                            {% if ev.get('event_markers') or ev.get('tense_aspect') %}
                            {% if ev.get('event_markers') %}<p><span class="field-label">事件关键词：</span>{{ ev.event_markers | join(', ') }}</p>{% endif %}
                            {% if ev.get('tense_aspect') %}<p><span class="field-label">时体标记：</span>{{ ev.tense_aspect }}</p>{% endif %}
                            {% endif %}

                            <!-- 事件级证据（折叠） -->
                            {% if ev.get('evidence') %}
                            <details class="details-block" style="margin-top: 10px;">
                                <summary>📄 查看本事件依据</summary>
                                <div style="margin-top: 6px; padding: 6px; background: #f0f8ff; border-radius: 4px; font-size: 0.95em;">
                                    <p><span class="field-label">事件证据：</span>
                                        {% for frag in ev.evidence %}
                                        <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                                        {% endfor %}
                                    </p>
                                </div>
                            </details>
                            {% endif %}

                        </div>
                        {% endfor %}
                        {% endif %}

                    </div>
                </details>
            </div>
        </div>
        {% endif %}

        <!-- 3. 空间感知 -->
        {% if data.get('spatial') %}
        <div class="section">
            <h3>3. 空间感知</h3>
            <div class="subsection">
                <!-- 主摘要（始终显示） -->
                {% if data.spatial.get('summary') %}
                <p><span class="field-label">空间摘要：</span>{{ data.spatial.summary }}</p>
                {% endif %}

                <!-- 折叠详情 -->
                <details class="details-block">
                    <summary>🔍 展开空间解析详情（含全局证据、语义标识与关系细节）</summary>
                    <div class="details-content">

                        <!-- 全局原文证据（始终显示，带说明） -->
                        {% if data.spatial.get('evidence') %}
                        <p>
                            <span class="field-label">全局原文证据：</span>
                            <small style="color: #666; font-style: italic;">（支撑整个空间判断的原始文本片段）</small><br>
                            {% for frag in data.spatial.evidence %}
                            <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                            {% endfor %}
                        </p>
                        {% endif %}

                        <!-- 空间事件列表 -->
                        {% if data.spatial.get('events') and data.spatial.events %}
                        <h4 style="margin-top: 16px; margin-bottom: 10px;">空间事件详情（共 {{ data.spatial.events | length }} 项）</h4>
                        {% for ev in data.spatial.events %}
                        <div class="relation-item" style="padding: 10px; background: #f9f9f9; border-radius: 6px; margin-bottom: 12px;">

                            <!-- 核心地点信息 -->
                            {% if ev.get('semantic_notation') %}<p><span class="field-label">语义标识：</span><code>{{ ev.semantic_notation }}</code></p>{% endif %}
                            {% if ev.get('experiencer') %}<p><span class="field-label">陈述主体：</span>{{ ev.experiencer }}</p>{% endif %}
                            {% if ev.get('places') %}<p><span class="field-label">地点：</span>{{ ev.places | join(', ') }}</p>{% endif %}
                            {% if ev.get('negated_places') %}<p><span class="field-label">被否定的地点：</span>{{ ev.negated_places | join(', ') }}</p>{% endif %}
                            {% if ev.get('cultural_or_institutional_spaces') %}<p><span class="field-label">制度性/文化空间：</span>{{ ev.cultural_or_institutional_spaces | join(', ') }}</p>{% endif %}

                            <!-- 空间描述 -->
                            {% if ev.get('layout_descriptions') or ev.get('orientation_descriptions') %}
                            {% if ev.get('layout_descriptions') %}<p><span class="field-label">空间布局：</span>{{ ev.layout_descriptions | join('; ') }}</p>{% endif %}
                            {% if ev.get('orientation_descriptions') %}<p><span class="field-label">方向/朝向：</span>{{ ev.orientation_descriptions | join('; ') }}</p>{% endif %}
                            {% endif %}

                            <!-- 语言与上下文线索 -->
                            {% if ev.get('spatial_event_markers') %}
                            <p><span class="field-label">事件关键词：</span>{{ ev.spatial_event_markers | join(', ') }}</p>
                            {% endif %}

                            <!-- 空间关系列表（作为子模块，折叠展示） -->
                            {% if ev.get('proximity_relations') and ev.proximity_relations %}
                            <details class="details-block" style="margin-top: 10px;">
                                <summary>🔍 展开空间关系详情（共 {{ ev.proximity_relations | length }} 项）</summary>
                                <div style="margin-top: 6px; padding: 6px; background: #f0f8ff; border-radius: 4px; font-size: 0.95em;">
                                    {% for rel in ev.proximity_relations %}
                                    <div class="relation-item" style="padding: 8px; background: #fff0f0; border-radius: 5px; margin-bottom: 8px; font-size: 0.95em;">
                                        {% if rel.get('actor') %}<p><span class="field-label">主动方：</span>{{ rel.actor }}</p>{% endif %}
                                        {% if rel.get('target') %}<p><span class="field-label">目标方：</span>{{ rel.target }}</p>{% endif %}
                                        {% if rel.get('relation_type') %}<p><span class="field-label">关系类型：</span>{{ rel.relation_type }}</p>{% endif %}
                                        {% if rel.get('distance_cm') is not none %}<p><span class="field-label">距离（cm）：</span>{{ rel.distance_cm }}</p>{% endif %}
                                        {% if rel.get('modifiers') %}<p><span class="field-label">修饰成分：</span>{{ rel.modifiers | join(', ') }}</p>{% endif %}
                                    </div>
                                    {% endfor %}
                                </div>
                            </details>
                            {% endif %}

                            <!-- 事件级证据（折叠） -->
                            {% if ev.get('evidence') %}
                            <details class="details-block" style="margin-top: 10px;">
                                <summary>📄 查看本事件依据</summary>
                                <div style="margin-top: 6px; padding: 6px; background: #f0f8ff; border-radius: 4px; font-size: 0.95em;">
                                    <p><span class="field-label">事件证据：</span>
                                        {% for frag in ev.evidence %}
                                        <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                                        {% endfor %}
                                    </p>
                                </div>
                            </details>
                            {% endif %}

                        </div>
                        {% endfor %}
                        {% endif %}

                    </div>
                </details>
            </div>
        </div>
        {% endif %}

        <!-- 4. 视觉感知 -->
        {% if data.get('visual') %}
        <div class="section">
            <h3>4. 视觉感知</h3>
            <div class="subsection">
                <!-- 主摘要（始终显示） -->
                {% if data.visual.get('summary') %}
                <p><span class="field-label">视觉摘要：</span>{{ data.visual.summary }}</p>
                {% endif %}

                <!-- 折叠详情 -->
                <details class="details-block">
                    <summary>🔍 展开视觉解析详情（含全局证据、语义标识与事件细节）</summary>
                    <div class="details-content">

                        <!-- 全局字段 -->
                        {% if data.visual.get('evidence') %}
                        <p>
                            <span class="field-label">全局原文证据：</span>
                            <small style="color: #666; font-style: italic;">（支撑整个视觉判断的原始文本片段）</small><br>
                            {% for frag in data.visual.evidence %}
                            <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                            {% endfor %}
                        </p>
                        {% endif %}

                        <!-- 视觉事件列表 -->
                        {% if data.visual.get('events') and data.visual.events %}
                        <h4 style="margin-top: 16px; margin-bottom: 10px;">视觉事件详情（共 {{ data.visual.events | length }} 项）</h4>
                        {% for ev in data.visual.events %}
                        <div class="relation-item" style="padding: 10px; background: #f9f9f9; border-radius: 6px; margin-bottom: 12px;">

                            <!-- 核心观察字段（含 salience） -->
                            {% if ev.get('semantic_notation') %}<p><span class="field-label">语义标识：</span><code>{{ ev.semantic_notation }}</code></p>{% endif %}
                            {% if ev.get('experiencer') %}<p><span class="field-label">观察者：</span>{{ ev.experiencer }}</p>{% endif %}
                            {% if ev.get('observed_entity') %}<p><span class="field-label">被观察对象：</span>{{ ev.observed_entity }}</p>{% endif %}
                            {% if ev.get('visual_objects') %}<p><span class="field-label">可见物体：</span>{{ ev.visual_objects | join(', ') }}</p>{% endif %}
                            {% if ev.get('visual_attributes') %}<p><span class="field-label">视觉属性：</span>{{ ev.visual_attributes | join(', ') }}</p>{% endif %}
                            {% if ev.get('visual_actions') %}<p><span class="field-label">可见动作：</span>{{ ev.visual_actions | join(', ') }}</p>{% endif %}
                            {% if ev.get('gaze_target') %}<p><span class="field-label">注视目标：</span>{{ ev.gaze_target }}</p>{% endif %}
                            {% if ev.get('eye_contact') %}<p><span class="field-label">眼神交互：</span>{{ ev.eye_contact | join(', ') }}</p>{% endif %}
                            {% if ev.get('facial_cues') %}<p><span class="field-label">面部线索：</span>{{ ev.facial_cues | join(', ') }}</p>{% endif %}
                            {% if ev.get('negated_observations') %}<p><span class="field-label">被否定的观察：</span>{{ ev.negated_observations | join(', ') }}</p>{% endif %}
                            {% if ev.get('salience') is not none %}<p><span class="field-label">显著性：</span>{{ "%.1f"|format(ev.salience) }}</p>{% endif %}

                            <!-- 感知条件与视线限制（原“环境与约束条件”） -->
                            {% if ev.get('lighting_conditions') or ev.get('visual_medium') or ev.get('occlusion_or_obstruction') %}
                            {% if ev.get('lighting_conditions') %}<p><span class="field-label">光照条件：</span>{{ ev.lighting_conditions | join(', ') }}</p>{% endif %}
                            {% if ev.get('visual_medium') %}<p><span class="field-label">视觉媒介：</span>{{ ev.visual_medium | join(', ') }}</p>{% endif %}
                            {% if ev.get('occlusion_or_obstruction') %}<p><span class="field-label">遮挡/阻碍：</span>{{ ev.occlusion_or_obstruction | join(', ') }}</p>{% endif %}
                            {% endif %}

                            <!-- 事件级证据与语义（折叠） -->
                            {% if ev.get('evidence') %}
                            <details class="details-block" style="margin-top: 10px;">
                                <summary>📄 查看本事件依据</summary>
                                <div style="margin-top: 6px; padding: 6px; background: #f0f8ff; border-radius: 4px; font-size: 0.95em;">
                                    <p><span class="field-label">事件证据：</span>
                                        {% for frag in ev.evidence %}
                                        <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                                        {% endfor %}
                                    </p>
                                </div>
                            </details>
                            {% endif %}

                        </div>
                        {% endfor %}
                        {% endif %}

                    </div>
                </details>
            </div>
        </div>
        {% endif %}

        <!-- 5. 听觉感知 -->
        {% if data.get('auditory') %}
        <div class="section">
            <h3>5. 听觉感知</h3>
            <div class="subsection">
                <!-- 主摘要（始终显示） -->
                {% if data.auditory.get('summary') %}
                <p><span class="field-label">听觉摘要：</span>{{ data.auditory.summary }}</p>
                {% endif %}

                <!-- 折叠详情 -->
                <details class="details-block">
                    <summary>🔍 展开听觉解析详情（含全局证据、语义标识与事件细节）</summary>
                    <div class="details-content">

                        <!-- 全局原文证据（始终显示，带说明） -->
                        {% if data.auditory.get('evidence') %}
                        <p>
                            <span class="field-label">全局原文证据：</span>
                            <small style="color: #666; font-style: italic;">（支撑整个听觉判断的原始文本片段）</small><br>
                            {% for frag in data.auditory.evidence %}
                            <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                            {% endfor %}
                        </p>
                        {% endif %}

                        <!-- 听觉事件列表 -->
                        {% if data.auditory.get('events') and data.auditory.events %}
                        <h4 style="margin-top: 16px; margin-bottom: 10px;">听觉事件详情（共 {{ data.auditory.events | length }} 项）</h4>
                        {% for ev in data.auditory.events %}
                        <div class="relation-item" style="padding: 10px; background: #f9f9f9; border-radius: 6px; margin-bottom: 12px;">

                            <!-- 核心听觉要素 -->
                            {% if ev.get('semantic_notation') %}<p><span class="field-label">语义标识：</span><code>{{ ev.semantic_notation }}</code></p>{% endif %}
                            {% if ev.get('experiencer') %}<p><span class="field-label">感知主体：</span>{{ ev.experiencer }}</p>{% endif %}
                            {% if ev.get('sound_source') %}<p><span class="field-label">声源：</span>{{ ev.sound_source }}</p>{% endif %}
                            {% if ev.get('auditory_content') %}<p><span class="field-label">听觉内容：</span>{{ ev.auditory_content | join(', ') }}</p>{% endif %}
                            {% if ev.get('is_primary_focus') is not none %}
                                <p><span class="field-label">是否为听觉焦点：</span>{{ '是' if ev.is_primary_focus else '否' }}</p>
                            {% endif %}

                            <!-- 声音特征 -->
                            {% if ev.get('prosody_cues') or ev.get('pause_description') or ev.get('intensity') is not none %}
                            {% if ev.get('prosody_cues') %}<p><span class="field-label">语调/韵律特征：</span>{{ ev.prosody_cues | join(', ') }}</p>{% endif %}
                            {% if ev.get('pause_description') %}<p><span class="field-label">停顿描述：</span>{{ ev.pause_description }}</p>{% endif %}
                            {% if ev.get('intensity') is not none %}
                                <p><span class="field-label">感知强度：</span>{{ "%.1f"|format(ev.intensity) }}（0.0–1.0 量化值）</p>
                            {% endif %}
                            {% endif %}

                            <!-- 环境与媒介 -->
                            {% if ev.get('auditory_medium') or ev.get('background_sounds') or ev.get('nonverbal_sounds') %}
                            {% if ev.get('auditory_medium') %}<p><span class="field-label">听觉媒介：</span>{{ ev.auditory_medium | join(', ') }}</p>{% endif %}
                            {% if ev.get('background_sounds') %}<p><span class="field-label">背景声音：</span>{{ ev.background_sounds | join(', ') }}</p>{% endif %}
                            {% if ev.get('nonverbal_sounds') %}<p><span class="field-label">非语言声音：</span>{{ ev.nonverbal_sounds | join(', ') }}</p>{% endif %}
                            {% endif %}

                            <!-- 否定观察 -->
                            {% if ev.get('negated_observations') %}
                            <p><span class="field-label">否定观察：</span>{{ ev.negated_observations | join(', ') }}</p>
                            {% endif %}

                            <!-- 事件级证据（折叠） -->
                            {% if ev.get('evidence') %}
                            <details class="details-block" style="margin-top: 10px;">
                                <summary>📄 查看本事件依据</summary>
                                <div style="margin-top: 6px; padding: 6px; background: #f0f8ff; border-radius: 4px; font-size: 0.95em;">
                                    <p><span class="field-label">事件证据：</span>
                                        {% for frag in ev.evidence %}
                                        <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                                        {% endfor %}
                                    </p>
                                </div>
                            </details>
                            {% endif %}

                        </div>
                        {% endfor %}
                        {% endif %}

                    </div>
                </details>
            </div>
        </div>
        {% endif %}

        <!-- 6. 嗅觉感知 -->
        {% if data.get('olfactory') %}
        <div class="section">
            <h3>6. 嗅觉感知</h3>
            <div class="subsection">
                <!-- 主摘要（始终显示） -->
                {% if data.olfactory.get('summary') %}
                <p><span class="field-label">嗅觉摘要：</span>{{ data.olfactory.summary }}</p>
                {% endif %}

                <!-- 折叠详情 -->
                <details class="details-block">
                    <summary>🔍 展开嗅觉解析详情（含全局证据、语义标识与事件细节）</summary>
                    <div class="details-content">

                        <!-- 全局原文证据（始终显示 + 说明） -->
                        {% if data.olfactory.get('evidence') %}
                        <p>
                            <span class="field-label">全局原文证据：</span>
                            <small style="color: #666; font-style: italic;">（支撑整个嗅觉判断的原始文本片段）</small><br>
                            {% for frag in data.olfactory.evidence %}
                            <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                            {% endfor %}
                        </p>
                        {% endif %}

                        <!-- 嗅觉事件列表 -->
                        {% if data.olfactory.get('events') and data.olfactory.events %}
                        <h4 style="margin-top: 16px; margin-bottom: 10px;">嗅觉事件详情（共 {{ data.olfactory.events | length }} 项）</h4>
                        {% for ev in data.olfactory.events %}
                        <div class="relation-item" style="padding: 10px; background: #f9f9f9; border-radius: 6px; margin-bottom: 12px;">

                            <!-- 核心气味要素 -->
                            {% if ev.get('semantic_notation') %}<p><span class="field-label">语义标识：</span><code>{{ ev.semantic_notation }}</code></p>{% endif %}
                            {% if ev.get('experiencer') %}<p><span class="field-label">感知主体：</span>{{ ev.experiencer }}</p>{% endif %}
                            {% if ev.get('odor_source') %}<p><span class="field-label">气味来源：</span>{{ ev.odor_source }}</p>{% endif %}
                            {% if ev.get('odor_descriptors') %}<p><span class="field-label">气味描述词：</span>{{ ev.odor_descriptors | join(', ') }}</p>{% endif %}
                            {% if ev.get('intensity') is not none %}
                                <p><span class="field-label">感知强度：</span>{{ "%.1f"|format(ev.intensity) }}（0.0–1.0 量化值）</p>
                            {% endif %}

                            <!-- 气味情感与评价 -->
                            {% if ev.get('odor_valence') %}
                            <p><span class="field-label">情感倾向：</span>{{ ev.odor_valence | join(', ') }}</p>
                            {% endif %}

                            <!-- 来源分类与行为响应 -->
                            {% if ev.get('odor_source_category') or ev.get('olfactory_actions') %}
                            {% if ev.get('odor_source_category') %}<p><span class="field-label">来源类别：</span>{{ ev.odor_source_category | join(', ') }}</p>{% endif %}
                            {% if ev.get('olfactory_actions') %}<p><span class="field-label">嗅觉相关动作：</span>{{ ev.olfactory_actions | join(', ') }}</p>{% endif %}
                            {% endif %}

                            <!-- 否定观察 -->
                            {% if ev.get('negated_observations') %}
                            <p><span class="field-label">否定观察：</span>{{ ev.negated_observations | join(', ') }}</p>
                            {% endif %}

                            <!-- 事件级证据（仅 evidence，语义已前置） -->
                            {% if ev.get('evidence') %}
                            <details class="details-block" style="margin-top: 10px;">
                                <summary>📄 查看本事件依据</summary>
                                <div style="margin-top: 6px; padding: 6px; background: #f0f8ff; border-radius: 4px; font-size: 0.95em;">
                                    <p><span class="field-label">事件证据：</span>
                                        {% for frag in ev.evidence %}
                                        <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                                        {% endfor %}
                                    </p>
                                </div>
                            </details>
                            {% endif %}

                        </div>
                        {% endfor %}
                        {% endif %}

                    </div>
                </details>
            </div>
        </div>
        {% endif %}

        <!-- 7. 触觉感知 -->
        {% if data.get('tactile') %}
        <div class="section">
            <h3>7. 触觉感知</h3>
            <div class="subsection">
                <!-- 主摘要（始终显示） -->
                {% if data.tactile.get('summary') %}
                <p><span class="field-label">触觉摘要：</span>{{ data.tactile.summary }}</p>
                {% endif %}

                <!-- 折叠详情 -->
                <details class="details-block">
                    <summary>🔍 展开触觉解析详情（含全局证据、语义标识与事件细节）</summary>
                    <div class="details-content">

                        <!-- 全局原文证据（带说明） -->
                        {% if data.tactile.get('evidence') %}
                        <p>
                            <span class="field-label">全局原文证据：</span>
                            <small style="color: #666; font-style: italic;">（支撑整个触觉判断的原始文本片段）</small><br>
                            {% for frag in data.tactile.evidence %}
                            <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                            {% endfor %}
                        </p>
                        {% endif %}

                        <!-- 触觉事件列表 -->
                        {% if data.tactile.get('events') and data.tactile.events %}
                        <h4 style="margin-top: 16px; margin-bottom: 10px;">触觉事件详情（共 {{ data.tactile.events | length }} 项）</h4>
                        {% for ev in data.tactile.events %}
                        <div class="relation-item" style="padding: 10px; background: #f9f9f9; border-radius: 6px; margin-bottom: 12px;">

                            <!-- 核心接触关系 -->
                            {% if ev.get('semantic_notation') %}<p><span class="field-label">语义标识：</span><code>{{ ev.semantic_notation }}</code></p>{% endif %}
                            {% if ev.get('experiencer') %}<p><span class="field-label">感知主体：</span>{{ ev.experiencer }}</p>{% endif %}
                            {% if ev.get('contact_initiator') %}<p><span class="field-label">接触发起方：</span>{{ ev.contact_initiator }}</p>{% endif %}
                            {% if ev.get('contact_target') %}<p><span class="field-label">接触对象：</span>{{ ev.contact_target }}</p>{% endif %}
                            {% if ev.get('body_part') %}<p><span class="field-label">身体部位：</span>{{ ev.body_part }}</p>{% endif %}
                            {% if ev.get('tactile_descriptors') %}<p><span class="field-label">触觉描述词：</span>{{ ev.tactile_descriptors | join(', ') }}</p>{% endif %}
                            {% if ev.get('intensity') is not none %}
                                <p><span class="field-label">感知强度：</span>{{ "%.1f"|format(ev.intensity) }}（0.0–1.0 量化值）</p>
                            {% endif %}

                            <!-- 物理属性维度（触觉核心特色！） -->
                            {% if ev.get('texture') or ev.get('temperature') or ev.get('pressure') or ev.get('moisture') or ev.get('vibration') or ev.get('motion') or ev.get('pain') or ev.get('contact') %}
                            {% if ev.get('texture') %}<p><span class="field-label">质地特征：</span>{{ ev.texture | join(', ') }}</p>{% endif %}
                            {% if ev.get('temperature') %}<p><span class="field-label">温度特征：</span>{{ ev.temperature | join(', ') }}</p>{% endif %}
                            {% if ev.get('pressure') %}<p><span class="field-label">压力特征：</span>{{ ev.pressure | join(', ') }}</p>{% endif %}
                            {% if ev.get('moisture') %}<p><span class="field-label">湿度特征：</span>{{ ev.moisture | join(', ') }}</p>{% endif %}
                            {% if ev.get('vibration') %}<p><span class="field-label">震动特征：</span>{{ ev.vibration | join(', ') }}</p>{% endif %}
                            {% if ev.get('motion') %}<p><span class="field-label">动态触觉：</span>{{ ev.motion | join(', ') }}</p>{% endif %}
                            {% if ev.get('pain') %}<p><span class="field-label">疼痛描述：</span>{{ ev.pain | join(', ') }}</p>{% endif %}
                            {% if ev.get('contact') %}<p><span class="field-label">接触方式/存在：</span>{{ ev.contact | join(', ') }}</p>{% endif %}
                            {% endif %}

                            <!-- 情感与意图 -->
                            {% if ev.get('tactile_intent_or_valence') %}
                            <p><span class="field-label">情感或意图：</span>{{ ev.tactile_intent_or_valence | join(', ') }}</p>
                            {% endif %}

                            <!-- 否定观察 -->
                            {% if ev.get('negated_observations') %}
                            <p><span class="field-label">否定观察：</span>{{ ev.negated_observations | join(', ') }}</p>
                            {% endif %}

                            <!-- 事件级证据（仅 evidence） -->
                            {% if ev.get('evidence') %}
                            <details class="details-block" style="margin-top: 10px;">
                                <summary>📄 查看本事件依据</summary>
                                <div style="margin-top: 6px; padding: 6px; background: #f0f8ff; border-radius: 4px; font-size: 0.95em;">
                                    <p><span class="field-label">事件证据：</span>
                                        {% for frag in ev.evidence %}
                                        <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                                        {% endfor %}
                                    </p>
                                </div>
                            </details>
                            {% endif %}

                        </div>
                        {% endfor %}
                        {% endif %}

                    </div>
                </details>
            </div>
        </div>
        {% endif %}

        <!-- 8. 味觉感知 -->
        {% if data.get('gustatory') %}
        <div class="section">
            <h3>8. 味觉感知</h3>
            <div class="subsection">
            <!-- 主摘要（始终显示） -->
            {% if data.gustatory.get('summary') %}
            <p><span class="field-label">味觉摘要：</span>{{ data.gustatory.summary }}</p>
            {% endif %}

            <!-- 折叠详情 -->
            <details class="details-block">
                <summary>🔍 展开味觉解析详情（含全局证据、语义标识与事件细节）</summary>
                <div class="details-content">

                    <!-- 全局原文证据（带说明） -->
                    {% if data.gustatory.get('evidence') %}
                    <p>
                        <span class="field-label">全局原文证据：</span>
                        <small style="color: #666; font-style: italic;">（支撑整个味觉判断的原始文本片段）</small><br>
                        {% for frag in data.gustatory.evidence %}
                        <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                        {% endfor %}
                    </p>
                    {% endif %}

                    <!-- 味觉事件列表 -->
                    {% if data.gustatory.get('events') and data.gustatory.events %}
                    <h4 style="margin-top: 16px; margin-bottom: 10px;">味觉事件详情（共 {{ data.gustatory.events | length }} 项）</h4>
                    {% for ev in data.gustatory.events %}
                    <div class="relation-item" style="padding: 10px; background: #f9f9f9; border-radius: 6px; margin-bottom: 12px;">

                        <!-- 核心摄入关系 -->
                        {% if ev.get('semantic_notation') %}<p><span class="field-label">语义标识：</span><code>{{ ev.semantic_notation }}</code></p>{% endif %}
                        {% if ev.get('experiencer') %}<p><span class="field-label">感知主体：</span>{{ ev.experiencer }}</p>{% endif %}
                        {% if ev.get('contact_initiator') %}<p><span class="field-label">摄入发起方：</span>{{ ev.contact_initiator }}</p>{% endif %}
                        {% if ev.get('taste_source') %}<p><span class="field-label">味道来源：</span>{{ ev.taste_source }}</p>{% endif %}
                        {% if ev.get('body_part') %}<p><span class="field-label">感受部位：</span>{{ ev.body_part }}</p>{% endif %}
                        {% if ev.get('taste_descriptors') %}<p><span class="field-label">味觉描述词：</span>{{ ev.taste_descriptors | join(', ') }}</p>{% endif %}
                        {% if ev.get('intensity') is not none %}
                            <p><span class="field-label">感知强度：</span>{{ "%.1f"|format(ev.intensity) }}（0.0–1.0 量化值）</p>
                        {% endif %}

                        <!-- 基础味型（经典五味） -->
                        {% if ev.get('sweet') or ev.get('salty') or ev.get('sour') or ev.get('bitter') or ev.get('umami') %}
                        {% if ev.get('sweet') %}<p><span class="field-label">甜味：</span>{{ ev.sweet | join(', ') }}</p>{% endif %}
                        {% if ev.get('salty') %}<p><span class="field-label">咸味：</span>{{ ev.salty | join(', ') }}</p>{% endif %}
                        {% if ev.get('sour') %}<p><span class="field-label">酸味：</span>{{ ev.sour | join(', ') }}</p>{% endif %}
                        {% if ev.get('bitter') %}<p><span class="field-label">苦味：</span>{{ ev.bitter | join(', ') }}</p>{% endif %}
                        {% if ev.get('umami') %}<p><span class="field-label">鲜味：</span>{{ ev.umami | join(', ') }}</p>{% endif %}
                        {% endif %}

                        <!-- 扩展风味与三叉神经刺激 -->
                        {% if ev.get('spicy') or ev.get('astringent') or ev.get('fatty') or ev.get('metallic') or ev.get('chemical') or ev.get('thermal') %}
                        {% if ev.get('spicy') %}<p><span class="field-label">辣/刺激感：</span>{{ ev.spicy | join(', ') }}</p>{% endif %}
                        {% if ev.get('astringent') %}<p><span class="field-label">涩味：</span>{{ ev.astringent | join(', ') }}</p>{% endif %}
                        {% if ev.get('fatty') %}<p><span class="field-label">油脂感：</span>{{ ev.fatty | join(', ') }}</p>{% endif %}
                        {% if ev.get('metallic') %}<p><span class="field-label">金属味：</span>{{ ev.metallic | join(', ') }}</p>{% endif %}
                        {% if ev.get('chemical') %}<p><span class="field-label">化学异味：</span>{{ ev.chemical | join(', ') }}</p>{% endif %}
                        {% if ev.get('thermal') %}<p><span class="field-label">清凉/灼热感：</span>{{ ev.thermal | join(', ') }}</p>{% endif %}
                        {% endif %}

                        <!-- 情感与意图 -->
                        {% if ev.get('intent_or_valence') %}
                        <p><span class="field-label">情感或意图：</span>{{ ev.intent_or_valence | join(', ') }}</p>
                        {% endif %}

                        <!-- 否定观察 -->
                        {% if ev.get('negated_observations') %}
                        <p><span class="field-label">否定观察：</span>{{ ev.negated_observations | join(', ') }}</p>
                        {% endif %}

                        <!-- 事件级证据（仅 evidence） -->
                        {% if ev.get('evidence') %}
                        <details class="details-block" style="margin-top: 10px;">
                            <summary>📄 查看本事件依据</summary>
                            <div style="margin-top: 6px; padding: 6px; background: #f0f8ff; border-radius: 4px; font-size: 0.95em;">
                                <p><span class="field-label">事件证据：</span>
                                    {% for frag in ev.evidence %}
                                    <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                                    {% endfor %}
                                </p>
                            </div>
                        </details>
                        {% endif %}

                    </div>
                    {% endfor %}
                    {% endif %}

                </div>
            </details>
            </div>
        </div>
        {% endif %}

        <!-- 9. 内感受 -->
        {% if data.get('interoceptive') %}
        <div class="section">
            <h3>9. 内感受</h3>
            <div class="subsection">
                <!-- 主摘要（始终显示） -->
                {% if data.interoceptive.get('summary') %}
                <p><span class="field-label">内感受摘要：</span>{{ data.interoceptive.summary }}</p>
                {% endif %}

                <!-- 折叠详情 -->
                <details class="details-block">
                    <summary>🔍 展开内感受解析详情（含全局证据、语义标识与事件细节）</summary>
                    <div class="details-content">

                        <!-- 全局原文证据 -->
                        {% if data.interoceptive.get('evidence') %}
                        <p>
                            <span class="field-label">全局原文证据：</span>
                            <small style="color: #666; font-style: italic;">（支撑整体内感受判断的原始文本片段）</small><br>
                            {% for frag in data.interoceptive.evidence %}
                            <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                            {% endfor %}
                        </p>
                        {% endif %}

                        <!-- 内感受事件列表 -->
                        {% if data.interoceptive.get('events') and data.interoceptive.events %}
                        <h4 style="margin-top: 16px; margin-bottom: 10px;">内感受事件详情（共 {{ data.interoceptive.events | length }} 项）</h4>
                        {% for ev in data.interoceptive.events %}
                        <div class="relation-item" style="padding: 10px; background: #f9f9f9; border-radius: 6px; margin-bottom: 12px;">

                            <!-- 核心元信息 -->
                            {% if ev.get('semantic_notation') %}<p><span class="field-label">语义标识：</span><code>{{ ev.semantic_notation }}</code></p>{% endif %}
                            {% if ev.get('experiencer') %}<p><span class="field-label">感知主体：</span>{{ ev.experiencer }}</p>{% endif %}
                            {% if ev.get('body_part') %}<p><span class="field-label">感受部位：</span>{{ ev.body_part }}</p>{% endif %}
                            {% if ev.get('intensity') is not none %}
                                <p><span class="field-label">感知强度：</span>{{ "%.1f"|format(ev.intensity) }}（0.0–1.0 量化值）</p>
                            {% endif %}

                            <!-- 通用身体感觉（非分类描述） -->
                            {% if ev.get('body_sensation') %}
                            <p><span class="field-label">非特异性描述：</span>{{ ev.body_sensation | join(', ') }}</p>
                            {% endif %}

                            <!-- 生理系统维度（分组呈现） -->
                            {% set has_systemic = ev.get('cardiac') or ev.get('respiratory') or ev.get('gastrointestinal') or ev.get('thermal') or ev.get('muscular') or ev.get('visceral_pressure') %}
                            {% if has_systemic %}
                            {% if ev.get('cardiac') %}<p><span class="field-label">心悸/心跳感：</span>{{ ev.cardiac | join(', ') }}</p>{% endif %}
                            {% if ev.get('respiratory') %}<p><span class="field-label">呼吸感：</span>{{ ev.respiratory | join(', ') }}</p>{% endif %}
                            {% if ev.get('gastrointestinal') %}<p><span class="field-label">胃肠感：</span>{{ ev.gastrointestinal | join(', ') }}</p>{% endif %}
                            {% if ev.get('thermal') %}<p><span class="field-label">体温感：</span>{{ ev.thermal | join(', ') }}</p>{% endif %}
                            {% if ev.get('muscular') %}<p><span class="field-label">肌肉感：</span>{{ ev.muscular | join(', ') }}</p>{% endif %}
                            {% if ev.get('visceral_pressure') %}<p><span class="field-label">压迫感：</span>{{ ev.visceral_pressure | join(', ') }}</p>{% endif %}
                            {% endif %}

                            <!-- 神经与稳态相关感受 -->
                            {% set has_neuro_homeostatic = ev.get('dizziness') or ev.get('nausea') or ev.get('fatigue') or ev.get('thirst_hunger') %}
                            {% if has_neuro_homeostatic %}
                            {% if ev.get('dizziness') %}<p><span class="field-label">眩晕/失衡感：</span>{{ ev.dizziness | join(', ') }}</p>{% endif %}
                            {% if ev.get('nausea') %}<p><span class="field-label">恶心/反胃感：</span>{{ ev.nausea | join(', ') }}</p>{% endif %}
                            {% if ev.get('fatigue') %}<p><span class="field-label">疲惫/虚脱感：</span>{{ ev.fatigue | join(', ') }}</p>{% endif %}
                            {% if ev.get('thirst_hunger') %}<p><span class="field-label">饥渴感：</span>{{ ev.thirst_hunger | join(', ') }}</p>{% endif %}
                            {% endif %}

                            <!-- 情感/意图倾向 -->
                            {% if ev.get('intent_or_valence') %}
                            <p><span class="field-label">情感或意图：</span>{{ ev.intent_or_valence | join(', ') }}</p>
                            {% endif %}

                            <!-- 否定观察 -->
                            {% if ev.get('negated_observations') %}
                            <p><span class="field-label">否定内容：</span>{{ ev.negated_observations | join(', ') }}</p>
                            {% endif %}

                            <!-- 事件级证据（仅 evidence） -->
                            {% if ev.get('evidence') %}
                            <details class="details-block" style="margin-top: 10px;">
                                <summary>📄 查看本事件依据</summary>
                                <div style="margin-top: 6px; padding: 6px; background: #f0f8ff; border-radius: 4px; font-size: 0.95em;">
                                    <p><span class="field-label">事件证据：</span>
                                        {% for frag in ev.evidence %}
                                        <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                                        {% endfor %}
                                    </p>
                                </div>
                            </details>
                            {% endif %}

                        </div>
                        {% endfor %}
                        {% endif %}

                    </div>
                </details>
            </div>
        </div>
        {% endif %}

        <!-- 10. 认知过程 -->
        {% if data.get('cognitive') %}
        <div class="section">
            <h3>10. 认知过程</h3>
            <div class="subsection">
                <!-- 主摘要（始终显示） -->
                {% if data.cognitive.get('summary') %}
                <p><span class="field-label">认知摘要：</span>{{ data.cognitive.summary }}</p>
                {% endif %}

                <!-- 折叠详情 -->
                <details class="details-block">
                    <summary>🔍 展开认知解析详情（含全局证据、语义标识与事件细节）</summary>
                    <div class="details-content">

                        <!-- 全局原文证据 -->
                        {% if data.cognitive.get('evidence') %}
                        <p>
                            <span class="field-label">全局原文证据：</span>
                            <small style="color: #666; font-style: italic;">（支撑整体认知判断的原始文本片段）</small><br>
                            {% for frag in data.cognitive.evidence %}
                            <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                            {% endfor %}
                        </p>
                        {% endif %}

                        <!-- 认知事件列表 -->
                        {% if data.cognitive.get('events') and data.cognitive.events %}
                        <h4 style="margin-top: 16px; margin-bottom: 10px;">认知事件详情（共 {{ data.cognitive.events | length }} 项）</h4>
                        {% for ev in data.cognitive.events %}
                        <div class="relation-item" style="padding: 10px; background: #f9f9f9; border-radius: 6px; margin-bottom: 12px;">

                            <!-- 核心元信息（前置） -->
                            {% if ev.get('semantic_notation') %}<p><span class="field-label">语义标识：</span><code>{{ ev.semantic_notation }}</code></p>{% endif %}
                            {% if ev.get('experiencer') %}<p><span class="field-label">认知主体：</span>{{ ev.experiencer }}</p>{% endif %}
                            {% if ev.get('target_entity') %}<p><span class="field-label">思维、想法、念头：</span>{{ ev.target_entity }}</p>{% endif %}
                            {% if ev.get('intensity') is not none %}
                                <p><span class="field-label">认知强度：</span>{{ "%.1f"|format(ev.intensity) }}（0.0–1.0，表确信度或负荷）</p>
                            {% endif %}

                            <!-- 原始显性思维（保留，作为兜底） -->
                            {% if ev.get('explicit_thought') %}
                            <p><span class="field-label">未分类思维文本：</span>{{ ev.explicit_thought | join('; ') }}</p>
                            {% endif %}

                            <!-- 基础认知功能 -->
                            {% set has_basic = ev.get('belief') or ev.get('memory_recall') or ev.get('intention') %}
                            {% if has_basic %}
                            {% if ev.get('belief') %}<p><span class="field-label">信念：</span>{{ ev.belief | join('; ') }}</p>{% endif %}
                            {% if ev.get('intention') %}<p><span class="field-label">意图：</span>{{ ev.intention | join('; ') }}</p>{% endif %}
                            {% if ev.get('memory_recall') %}<p><span class="field-label">记忆提取：</span>{{ ev.memory_recall | join('; ') }}</p>{% endif %}
                            {% endif %}

                            <!-- 高阶认知功能 -->
                            {% set has_higher = ev.get('inference') or ev.get('problem_solving') or ev.get('metacognition') %}
                            {% if has_higher %}
                            {% if ev.get('inference') %}<p><span class="field-label">推理：</span>{{ ev.inference | join('; ') }}</p>{% endif %}
                            {% if ev.get('problem_solving') %}<p><span class="field-label">问题解决思路：</span>{{ ev.problem_solving | join('; ') }}</p>{% endif %}
                            {% if ev.get('metacognition') %}<p><span class="field-label">元认知（对思维的反思）：</span>{{ ev.metacognition | join('; ') }}</p>{% endif %}
                            {% endif %}

                            <!-- 情感耦合的认知 -->
                            {% set has_affective = ev.get('evaluation') or ev.get('doubt_or_uncertainty') %}
                            {% if has_affective %}
                            {% if ev.get('evaluation') %}<p><span class="field-label">价值判断：</span>{{ ev.evaluation | join('; ') }}</p>{% endif %}
                            {% if ev.get('doubt_or_uncertainty') %}<p><span class="field-label">怀疑/不确定：</span>{{ ev.doubt_or_uncertainty | join('; ') }}</p>{% endif %}
                            {% endif %}

                            <!-- 否定认知 -->
                            {% if ev.get('negated_cognitions') %}
                            <p><span class="field-label">否定内容：</span>{{ ev.negated_cognitions | join('; ') }}</p>
                            {% endif %}

                            <!-- 认知情感倾向 -->
                            {% if ev.get('cognitive_valence') %}
                            <p><span class="field-label">情感色彩：</span>{{ ev.cognitive_valence | join('; ') }}</p>
                            {% endif %}

                            <!-- 事件级证据（仅 evidence） -->
                            {% if ev.get('evidence') %}
                            <details class="details-block" style="margin-top: 10px;">
                                <summary>📄 查看本事件依据</summary>
                                <div style="margin-top: 6px; padding: 6px; background: #f0f8ff; border-radius: 4px; font-size: 0.95em;">
                                    <p><span class="field-label">事件证据：</span>
                                        {% for frag in ev.evidence %}
                                        <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                                        {% endfor %}
                                    </p>
                                </div>
                            </details>
                            {% endif %}

                        </div>
                        {% endfor %}
                        {% endif %}

                    </div>
                </details>
            </div>
        </div>
        {% endif %}

        <!-- 11. 躯体化表现 -->
        {% if data.get('bodily') %}
        <div class="section">
            <h3>11. 躯体化表现</h3>
            <div class="subsection">
                <!-- 主摘要（始终显示） -->
                {% if data.bodily.get('summary') %}
                <p><span class="field-label">躯体化摘要：</span>{{ data.bodily.summary }}</p>
                {% endif %}

                <!-- 折叠详情 -->
                <details class="details-block">
                    <summary>🔍 展开躯体化解析详情（含全局证据、语义标识与事件细节）</summary>
                    <div class="details-content">

                        <!-- 全局原文证据 -->
                        {% if data.bodily.get('evidence') %}
                        <p>
                            <span class="field-label">全局原文证据：</span>
                            <small style="color: #666; font-style: italic;">（支撑整体躯体化判断的原始文本片段）</small><br>
                            {% for frag in data.bodily.evidence %}
                            <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                            {% endfor %}
                        </p>
                        {% endif %}

                        <!-- 躯体化事件列表 -->
                        {% if data.bodily.get('events') and data.bodily.events %}
                        <h4 style="margin-top: 16px; margin-bottom: 10px;">躯体化事件详情（共 {{ data.bodily.events | length }} 项）</h4>
                        {% for ev in data.bodily.events %}
                        <div class="relation-item" style="padding: 10px; background: #f9f9f9; border-radius: 6px; margin-bottom: 12px;">

                            <!-- 核心元信息（前置） -->
                            {% if ev.get('semantic_notation') %}<p><span class="field-label">语义标识：</span><code>{{ ev.semantic_notation }}</code></p>{% endif %}
                            {% if ev.get('experiencer') %}<p><span class="field-label">行为主体：</span>{{ ev.experiencer }}</p>{% endif %}
                            {% if ev.get('observer') %}<p><span class="field-label">观察者：</span>{{ ev.observer }}</p>{% endif %}
                            {% if ev.get('intensity') is not none %}
                                <p><span class="field-label">表现强度：</span>{{ "%.1f"|format(ev.intensity) }}（0.0–1.0，表显著程度）</p>
                            {% endif %}

                            <!-- 姿态与运动 -->
                            {% set has_posture_motion = ev.get('posture') or ev.get('movement_direction') %}
                            {% if has_posture_motion %}
                            {% if ev.get('posture') %}<p><span class="field-label">静态姿态：</span>{{ ev.posture }}</p>{% endif %}
                            {% if ev.get('movement_direction') %}<p><span class="field-label">运动方向/趋势：</span>{{ ev.movement_direction }}</p>{% endif %}
                            {% endif %}

                            <!-- 外显行为系统 -->
                            {% set has_expressive = ev.get('facial_expression') or ev.get('vocal_behavior') or ev.get('motor_behavior') %}
                            {% if has_expressive %}
                            {% if ev.get('facial_expression') %}<p><span class="field-label">面部表情：</span>{{ ev.facial_expression | join('; ') }}</p>{% endif %}
                            {% if ev.get('vocal_behavior') %}<p><span class="field-label">声音表现：</span>{{ ev.vocal_behavior | join('; ') }}</p>{% endif %}
                            {% if ev.get('motor_behavior') %}<p><span class="field-label">动作行为：</span>{{ ev.motor_behavior | join('; ') }}</p>{% endif %}
                            {% endif %}

                            <!-- 自主神经系统反应 -->
                            {% if ev.get('autonomic_signs') %}
                            <p><span class="field-label">生理唤醒表现：</span>{{ ev.autonomic_signs | join('; ') }}</p>
                            {% endif %}

                            <!-- 应激防御反应 -->
                            {% if ev.get('freeze_or_faint') %}
                            <p><span class="field-label">冻结/晕厥类反应：</span>{{ ev.freeze_or_faint | join('; ') }}</p>
                            {% endif %}

                            <!-- 原始未分类行为（兜底） -->
                            {% if ev.get('observable_behavior') %}
                            <p><span class="field-label">原始可观测行为：</span>{{ ev.observable_behavior | join('; ') }}</p>
                            {% endif %}

                            <!-- 事件级证据（仅 evidence） -->
                            {% if ev.get('evidence') %}
                            <details class="details-block" style="margin-top: 10px;">
                                <summary>📄 查看本事件依据</summary>
                                <div style="margin-top: 6px; padding: 6px; background: #f0f8ff; border-radius: 4px; font-size: 0.95em;">
                                    <p><span class="field-label">事件证据：</span>
                                        {% for frag in ev.evidence %}
                                        <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                                        {% endfor %}
                                    </p>
                                </div>
                            </details>
                            {% endif %}

                        </div>
                        {% endfor %}
                        {% endif %}

                    </div>
                </details>
            </div>
        </div>
        {% endif %}

        <!-- 12. 情感状态 -->
        {% if data.get('emotional') %}
        <div class="section">
            <h3>12. 情感状态</h3>
            <div class="subsection">
                <!-- 主摘要（始终显示） -->
                {% if data.emotional.get('summary') %}
                <p><span class="field-label">情感摘要：</span>{{ data.emotional.summary }}</p>
                {% endif %}

                <!-- 折叠详情 -->
                <details class="details-block">
                    <summary>🔍 展开情感解析详情（含全局证据、语义标识与事件细节）</summary>
                    <div class="details-content">

                        <!-- 全局原文证据 -->
                        {% if data.emotional.get('evidence') %}
                        <p>
                            <span class="field-label">全局原文证据：</span>
                            <small style="color: #666; font-style: italic;">（支撑整体情感判断的原始文本片段）</small><br>
                            {% for frag in data.emotional.evidence %}
                            <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                            {% endfor %}
                        </p>
                        {% endif %}

                        <!-- 情感事件列表 -->
                        {% if data.emotional.get('events') and data.emotional.events %}
                        <h4 style="margin-top: 16px; margin-bottom: 10px;">情感事件详情（共 {{ data.emotional.events | length }} 项）</h4>
                        {% for ev in data.emotional.events %}
                        <div class="relation-item" style="padding: 10px; background: #f9f9f9; border-radius: 6px; margin-bottom: 12px;">

                            <!-- 核心元信息（前置） -->
                            {% if ev.get('semantic_notation') %}
                            <p><span class="field-label">语义标识：</span><code>{{ ev.semantic_notation }}</code></p>
                            {% endif %}
                            {% if ev.get('experiencer') %}
                            <p><span class="field-label">情绪主体：</span>{{ ev.experiencer }}</p>
                            {% endif %}
                            {% if ev.get('emotion_labels') %}
                            <p><span class="field-label">情绪标签：</span>{{ ev.emotion_labels | join('; ') }}</p>
                            {% endif %}

                            <!-- 情感表达模式（规范取值） -->
                            {% if ev.get('expression_mode') %}
                            <p><span class="field-label">表达模式：</span>
                                <span style="font-family: monospace; background: #f8f9fa; padding: 2px 6px; border-radius: 3px;">
                                    {{ ev.expression_mode }}
                                </span>
                                <small style="color: #7f8c8d; margin-left: 6px;">
                                    {% if ev.expression_mode == 'self_report' %}
                                        （第一人称自述）
                                    {% elif ev.expression_mode == 'observed_behavior' %}
                                        （他人观察到的行为）
                                    {% elif ev.expression_mode == 'narrator_attribution' %}
                                        （叙述者归因）
                                    {% elif ev.expression_mode == 'explicit' %}
                                        （直接陈述）
                                    {% elif ev.expression_mode == 'implicit' %}
                                        （间接暗示：行为/躯体/环境线索）
                                    {% elif ev.expression_mode == 'projected' %}
                                        （情绪投射至他人）
                                    {% else %}
                                        （{{ ev.expression_mode }}）
                                    {% endif %}
                                </small>
                            </p>
                            {% endif %}

                            <!-- 情感维度系统（垂直排列，统一格式） -->
                            {% if ev.get('valence') is not none %}
                            <p><span class="field-label">效价（Valence）：</span>{{ "%.1f"|format(ev.valence) }}（-1=负向，0=中性，+1=正向）</p>
                            {% endif %}
                            {% if ev.get('arousal') is not none %}
                            <p><span class="field-label">唤醒度（Arousal）：</span>{{ "%.1f"|format(ev.arousal) }}（0=平静，1=激动）</p>
                            {% endif %}
                            {% if ev.get('intensity') is not none %}
                            <p><span class="field-label">主观强度：</span>{{ "%.1f"|format(ev.intensity) }}（0.0–1.0，表情绪强烈程度）</p>
                            {% endif %}

                            <!-- 事件级证据 -->
                            {% if ev.get('evidence') %}
                            <details class="details-block" style="margin-top: 10px;">
                                <summary>📄 查看本事件依据</summary>
                                <div style="margin-top: 6px; padding: 6px; background: #f0f8ff; border-radius: 4px; font-size: 0.95em;">
                                    <p><span class="field-label">事件证据：</span>
                                        {% for frag in ev.evidence %}
                                        <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                                        {% endfor %}
                                    </p>
                                </div>
                            </details>
                            {% endif %}

                        </div>
                        {% endfor %}
                        {% endif %}

                    </div>
                </details>
            </div>
        </div>
        {% endif %}

        <!-- 13. 社会关系 -->
        {% if data.get('social_relation') %}
        <div class="section">
            <h3>13. 社会关系</h3>
            <div class="subsection">
                <!-- 主摘要（始终显示） -->
                {% if data.social_relation.get('summary') %}
                <p><span class="field-label">关系摘要：</span>{{ data.social_relation.summary }}</p>
                {% endif %}

                <!-- 折叠详情 -->
                <details class="details-block">
                    <summary>🔍 展开社会关系解析详情（含全局证据、语义标识与事件细节）</summary>
                    <div class="details-content">

                        <!-- 全局原文证据 -->
                        {% if data.social_relation.get('evidence') %}
                        <p>
                            <span class="field-label">全局原文证据：</span>
                            <small style="color: #666; font-style: italic;">（支撑整体关系判断的原始文本片段）</small><br>
                            {% for frag in data.social_relation.evidence %}
                            <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                            {% endfor %}
                        </p>
                        {% endif %}

                        <!-- 社会关系事件列表 -->
                        {% if data.social_relation.get('events') and data.social_relation.events %}
                        <h4 style="margin-top: 16px; margin-bottom: 10px;">关系事件详情（共 {{ data.social_relation.events | length }} 项）</h4>
                        {% for ev in data.social_relation.events %}
                        <div class="relation-item" style="padding: 10px; background: #f9f9f9; border-radius: 6px; margin-bottom: 12px;">

                            <!-- 核心元信息（前置） -->
                            {% if ev.get('semantic_notation') %}
                            <p><span class="field-label">语义标识：</span><code>{{ ev.semantic_notation }}</code></p>
                            {% endif %}

                            <!-- 关系方向性处理 -->
                            {% if ev.get('source') and ev.get('target') %}
                            <p><span class="field-label">关系主体 → 对象：</span><strong>{{ ev.source }}</strong> → <strong>{{ ev.target }}</strong></p>
                            {% elif ev.get('participants') %}
                            <p><span class="field-label">参与者：</span>{{ ev.participants | join('; ') }}</p>
                            {% endif %}

                            <!-- 自然语言关系类型 -->
                            {% if ev.get('relation_type') %}
                            <p><span class="field-label">关系类型：</span>{{ ev.relation_type }}</p>
                            {% endif %}

                            <!-- 置信度（格式与认知强度一致） -->
                            {% if ev.get('confidence') is not none %}
                            <p><span class="field-label">判断置信度：</span>{{ "%.1f"|format(ev.confidence) }}（0.0–1.0，表确信程度）</p>
                            {% endif %}

                            <!-- 事件级证据（仅 evidence） -->
                            {% if ev.get('evidence') %}
                            <details class="details-block" style="margin-top: 10px;">
                                <summary>📄 查看本事件依据</summary>
                                <div style="margin-top: 6px; padding: 6px; background: #f0f8ff; border-radius: 4px; font-size: 0.95em;">
                                    <p><span class="field-label">事件证据：</span>
                                        {% for frag in ev.evidence %}
                                        <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                                        {% endfor %}
                                    </p>
                                </div>
                            </details>
                            {% endif %}

                        </div>
                        {% endfor %}
                        {% endif %}

                    </div>
                </details>
            </div>
        </div>
        {% endif %}

        <!-- 14. 合理推演 -->
        {% if data.get('inference') %}
        <div class="section">
            <h3>14. 合理推演</h3>
            <div class="subsection">
                <!-- 主摘要（始终显示） -->
                {% if data.inference.get('summary') %}
                <p><span class="field-label">推演摘要：</span>{{ data.inference.summary }}</p>
                {% endif %}

                <!-- 折叠详情 -->
                <details class="details-block">
                    <summary>🔍 展开推演解析详情（含全局证据、语义标识与事件溯源）</summary>
                    <div class="details-content">

                        <!-- 全局原文证据 -->
                        {% if data.inference.get('evidence') %}
                        <p>
                            <span class="field-label">全局原文证据：</span>
                            <small style="color: #666; font-style: italic;">（支撑整体推演判断的原始文本片段）</small><br>
                            {% for frag in data.inference.evidence %}
                            <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                            {% endfor %}
                        </p>
                        {% endif %}

                        <!-- 推演事件列表 -->
                        {% if data.inference.get('events') and data.inference.events %}
                        <h4 style="margin-top: 16px; margin-bottom: 10px;">推演事件详情（共 {{ data.inference.events | length }} 项）</h4>
                        {% for ev in data.inference.events %}
                        <div class="relation-item" style="padding: 10px; background: #f8f9fa; border-radius: 6px; margin-bottom: 12px; border-left: 4px solid #9b59b6;">

                            <!-- 核心元信息（前置） -->
                            {% if ev.get('semantic_notation') %}
                            <p><span class="field-label">语义标识：</span><code>{{ ev.semantic_notation }}</code></p>
                            {% endif %}

                            <!-- 推理主体与结论 -->
                            {% if ev.get('experiencer') %}
                            <p><span class="field-label">推演主体：</span>{{ ev.experiencer }}</p>
                            {% endif %}
                            {% if ev.get('inferred_proposition') %}
                            <p><span class="field-label">推演结论：</span>{{ ev.inferred_proposition }}</p>
                            {% endif %}

                            <!-- 推理类型（规范取值） -->
                            {% if ev.get('inference_type') %}
                            <p><span class="field-label">推理类型：</span>
                                <span style="font-family: monospace; background: #eef2f7; padding: 2px 6px; border-radius: 3px;">
                                    {{ ev.inference_type }}
                                </span>
                                <small style="color: #7f8c8d; margin-left: 6px;">
                                    {% if ev.inference_type == 'causal' %}（因果推断）
                                    {% elif ev.inference_type == 'temporal' %}（时序推断）
                                    {% elif ev.inference_type == 'intentional' %}（意图推断）
                                    {% elif ev.inference_type == 'belief' %}（信念推断）
                                    {% elif ev.inference_type == 'contradiction' %}（矛盾检测）
                                    {% elif ev.inference_type == 'consistency_check' %}（一致性校验）
                                    {% elif ev.inference_type == 'counterfactual' %}（反事实推断）
                                    {% elif ev.inference_type == 'abductive' %}（溯因推断）
                                    {% elif ev.inference_type == 'normative' %}（规范性推断）
                                    {% elif ev.inference_type == 'social_attribution' %}（社会归因）
                                    {% elif ev.inference_type == 'state_transition' %}（状态转移推断）
                                    {% elif ev.inference_type == 'predictive' %}（预测性推断）
                                    {% elif ev.inference_type == 'analogical' %}（类比推断）
                                    {% else %}（未知类型：{{ ev.inference_type }}）
                                    {% endif %}
                                </small>
                            </p>
                            {% endif %}

                            <!-- 锚点：链接底层感知事件 -->
                            {% if ev.get('anchor_points') %}
                            <p>
                                <span class="field-label">感知锚点：</span>
                                <small style="color: #666;">（引用的底层事件语义标识）</small><br>
                                <code>{{ ev.anchor_points | join('; ') }}</code>
                            </p>
                            {% endif %}

                            <!-- 元属性：极性、模态、范围 -->
                            <div style="display: flex; flex-wrap: wrap; gap: 12px; margin-top: 8px; font-size: 0.95em; color: #555;">
                                {% if ev.get('polarity') %}
                                <div>
                                    <span class="field-label">命题极性：</span>
                                    {% if ev.polarity == 'positive' %}
                                        <span style="color: #27ae60;">积极</span>
                                    {% elif ev.polarity == 'negative' %}
                                        <span style="color: #e74c3c;">消极</span>
                                    {% elif ev.polarity == 'neutral' %}
                                        <span style="color: #7f8c8d;">中性</span>
                                    {% endif %}
                                </div>
                                {% endif %}

                                {% if ev.get('context_modality') %}
                                <div><span class="field-label">语境模态：</span>
                                    <span style="font-family: monospace;">{{ ev.context_modality }}</span>
                                    <small style="color: #7f8c8d;">
                                        {% if ev.context_modality == 'epistemic' %}（认知可能）
                                        {% elif ev.context_modality == 'deontic' %}（义务/许可）
                                        {% elif ev.context_modality == 'bouletic' %}（愿望/偏好）
                                        {% elif ev.context_modality == 'alethic' %}（逻辑必然）
                                        {% else %}（{{ ev.context_modality }}）
                                        {% endif %}
                                    </small>
                                </div>
                                {% endif %}

                                {% if ev.get('scope') %}
                                <div><span class="field-label">适用范围：</span>{{ ev.scope }}</div>
                                {% endif %}
                            </div>

                            <!-- 事件级证据 -->
                            {% if ev.get('evidence') %}
                            <details class="details-block" style="margin-top: 12px;">
                                <summary>📄 查看本推演原始依据</summary>
                                <div style="margin-top: 6px; padding: 6px; background: #f5f6fa; border-radius: 4px; font-size: 0.95em;">
                                    <p><span class="field-label">原始文本证据：</span>
                                        {% for frag in ev.evidence %}
                                        <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                                        {% endfor %}
                                    </p>
                                </div>
                            </details>
                            {% endif %}

                        </div>
                        {% endfor %}
                        {% endif %}

                    </div>
                </details>
            </div>
        </div>
        {% endif %}

        <!-- 15. 显性动机 -->
        {% if data.get('explicit_motivation') %}
        <div class="section">
            <h3>15. 显性动机</h3>
            <div class="subsection">
                <!-- 主摘要 -->
                {% if data.explicit_motivation.get('summary') %}
                <p><span class="field-label">显性动因摘要：</span>{{ data.explicit_motivation.summary }}</p>
                {% endif %}

                <!-- 折叠详情 -->
                <details class="details-block">
                    <summary>🔍 展开深度动因解析（含全局证据、语义标识与事件级溯源）</summary>
                    <div class="details-content">

                        <!-- 全局字段 -->
                        {% if data.explicit_motivation.get('evidence') %}
                        <p>
                            <span class="field-label">全局原文证据：</span>
                            {% for frag in data.explicit_motivation.evidence %}
                            <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                            {% endfor %}
                        </p>
                        {% endif %}

                        <!-- 动机事件列表 -->
                        {% if data.explicit_motivation.get('events') and data.explicit_motivation.events %}
                        <h4 style="margin-top: 16px; margin-bottom: 10px;">显性动机事件（共 {{ data.explicit_motivation.events | length }} 项）</h4>
                        {% for ev in data.explicit_motivation.events %}
                        <div class="relation-item" style="padding: 12px; background: #fff9f0; border-radius: 6px; margin-bottom: 14px; border-left: 4px solid #e67e22;">

                            <!-- 核心元信息（前置） -->
                            {% if ev.get('motivation_category') %}
                            <p><span class="field-label">动机类型：</span>
                                <span style="font-family: monospace; background: #fdf6e3; padding: 2px 6px; border-radius: 3px;">
                                    {{ ev.motivation_category }}
                                </span>
                            </p>
                            {% endif %}
                            {% if ev.get('semantic_notation') %}
                            <p><span class="field-label">语义标识：</span><code>{{ ev.semantic_notation }}</code></p>
                            {% endif %}
                            {% if ev.get('experiencer') %}
                            <p><span class="field-label">陈述主体：</span>{{ ev.experiencer }}</p>
                            {% endif %}

                            <!-- 原文证据（始终显示） -->
                            {% if ev.get('evidence') %}
                            <p><span class="field-label">原始陈述：</span>
                                {% for frag in ev.evidence %}
                                <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                                {% endfor %}
                            </p>
                            {% endif %}

                            <!-- 情感动机（折叠） -->
                            {% if ev.get('core_driver') or ev.get('care_expression') or ev.get('separation_anxiety') or ev.get('protective_intent') %}
                            <details class="details-block" style="margin-top: 10px;">
                                <summary>❤️ 情感与关怀驱动</summary>
                                <div style="margin-top: 6px; padding: 8px; background: #fdf6e3; border-radius: 4px; font-size: 0.95em;">
                                    {% if ev.get('core_driver') %}<p><span class="field-label">根本驱动力：</span>{{ ev.core_driver | join('; ') }}</p>{% endif %}
                                    {% if ev.get('care_expression') %}<p><span class="field-label">关怀表达：</span>{{ ev.care_expression | join('; ') }}</p>{% endif %}
                                    {% if ev.get('separation_anxiety') %}<p><span class="field-label">分离焦虑：</span>{{ ev.separation_anxiety | join('; ') }}</p>{% endif %}
                                    {% if ev.get('protective_intent') %}<p><span class="field-label">保护意图：</span>{{ ev.protective_intent | join('; ') }}</p>{% endif %}
                                </div>
                            </details>
                            {% endif %}

                            <!-- 社会控制（折叠） -->
                            {% if ev.get('resource_control') or ev.get('survival_imperative') or ev.get('social_enforcement_mechanism') %}
                            <details class="details-block" style="margin-top: 10px;">
                                <summary>⚖️ 社会控制与服从压力</summary>
                                <div style="margin-top: 6px; padding: 8px; background: #f0f9ff; border-radius: 4px; font-size: 0.95em;">
                                    {% if ev.get('resource_control') %}<p><span class="field-label">资源控制：</span>{{ ev.resource_control | join('; ') }}</p>{% endif %}
                                    {% if ev.get('survival_imperative') %}<p><span class="field-label">生存性服从：</span>{{ ev.survival_imperative | join('; ') }}</p>{% endif %}
                                    {% if ev.get('social_enforcement_mechanism') %}<p><span class="field-label">社会规范压力：</span>{{ ev.social_enforcement_mechanism | join('; ') }}</p>{% endif %}
                                </div>
                            </details>
                            {% endif %}

                            <!-- 内化压迫（显眼警示） -->
                            {% if ev.get('internalized_oppression') %}
                            <div style="margin-top: 10px; padding: 8px; background: #ffecec; border-left: 3px solid #e74c3c; border-radius: 4px;">
                                <strong>🩹 内化压迫（用户自我贬低/正当化伤害）：</strong>
                                <p>{{ ev.internalized_oppression | join('; ') }}</p>
                            </div>
                            {% endif %}

                            <!-- 权力结构（仅当显性描述） -->
                            {% if ev.get('power_asymmetry') %}
                            <details class="details-block" style="margin-top: 10px;">
                                <summary>🔐 用户自述的权力不对称</summary>
                                <div style="margin-top: 6px; padding: 8px; background: #f8f0ff; border-radius: 4px; font-size: 0.95em;">
                                    {% if ev.power_asymmetry.get('control_axis') %}
                                    <p><span class="field-label">控制方式：</span>{{ ev.power_asymmetry.control_axis | join(', ') }}</p>
                                    {% endif %}
                                    {% if ev.power_asymmetry.get('threat_vector') %}
                                    <p><span class="field-label">威胁手段：</span>{{ ev.power_asymmetry.threat_vector | join(', ') }}</p>
                                    {% endif %}
                                    {% if ev.power_asymmetry.get('evidence') %}
                                    <p><span class="field-label">原文证据：</span>
                                        {% for frag in ev.power_asymmetry.evidence %}
                                        <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                                        {% endfor %}
                                    </p>
                                    {% endif %}
                                </div>
                            </details>
                            {% endif %}

                            <!-- 话术策略（折叠） -->
                            {% if ev.get('narrative_distortion') %}
                            <details class="details-block" style="margin-top: 10px;">
                                <summary>🎭 用户自述的话术策略</summary>
                                <div style="margin-top: 6px; padding: 8px; background: #f0fff0; border-radius: 4px; font-size: 0.95em;">
                                    {% if ev.narrative_distortion.get('self_justification') %}
                                    <p><span class="field-label">自我合理化：</span>“{{ ev.narrative_distortion.self_justification }}”</p>
                                    {% endif %}
                                    {% if ev.narrative_distortion.get('blame_shift') %}
                                    <p><span class="field-label">责任转嫁：</span>“{{ ev.narrative_distortion.blame_shift }}”</p>
                                    {% endif %}
                                    {% if ev.narrative_distortion.get('moral_licensing') %}
                                    <p><span class="field-label">道德豁免：</span>“{{ ev.narrative_distortion.moral_licensing }}”</p>
                                    {% endif %}
                                    {% if ev.narrative_distortion.get('evidence') %}
                                    <p><span class="field-label">话术证据：</span>
                                        {% for frag in ev.narrative_distortion.evidence %}
                                        <code>"{{ frag }}"</code>{% if not loop.last %}；{% endif %}
                                        {% endfor %}
                                    </p>
                                    {% endif %}
                                </div>
                            </details>
                            {% endif %}

                        </div>
                        {% endfor %}
                        {% endif %}

                    </div>
                </details>
            </div>
        </div>
        {% endif %}

        <!-- 16. 合理建议 -->
        {% if data.get('rational_advice') %}
        <div class="section">
            <h3>16. 合理建议</h3>
            <div class="subsection">
                <!-- 主摘要 -->
                {% if data.rational_advice.get('summary') %}
                <p><span class="field-label">建议概述：</span>{{ data.rational_advice.summary }}</p>
                {% endif %}
                {% if data.rational_advice.get('semantic_notation') %}
                <p><span class="field-label">语义标识：</span><code>{{ data.rational_advice.semantic_notation }}</code></p>
                {% endif %}

                <details class="details-block">
                    <summary>🔍 展开完整建议方案（含依据、代价评估与文化适配）</summary>
                    <div class="details-content">

                        <!-- 依据：语义标识 -->
                        {% if data.rational_advice.get('evidence') %}
                        <p><span class="field-label">建议依据（动机语义标识）：</span>
                            <code>{{ data.rational_advice.evidence | join(', ') }}</code>
                        </p>
                        {% endif %}

                        <!-- 安全优先干预 -->
                        {% if data.rational_advice.get('safety_first_intervention') %}
                        <h4 style="color: #c0392b; margin-top: 16px;">⚠️ 安全优先干预（立即执行）</h4>
                        <ul class="advice-list" style="background: #fff5f5; padding: 10px; border-left: 3px solid #e74c3c;">
                            {% for item in data.rational_advice.safety_first_intervention %}
                            <li>{{ item }}</li>
                            {% endfor %}
                        </ul>
                        {% endif %}

                        <!-- 系统杠杆点 -->
                        {% if data.rational_advice.get('systemic_leverage_point') %}
                        <h4 style="margin-top: 16px;">🎯 系统杠杆点（关键突破口）</h4>
                        <ul class="advice-list">
                            {% for item in data.rational_advice.systemic_leverage_point %}
                            <li>{{ item }}</li>
                            {% endfor %}
                        </ul>
                        {% endif %}

                        <!-- 分阶段策略 -->
                        {% if data.rational_advice.get('incremental_strategy') %}
                        <h4 style="margin-top: 16px;">📈 分阶段策略（低风险渐进）</h4>
                        <div class="advice-list" style="margin-bottom: 16px;">
                            {% for step in data.rational_advice.incremental_strategy %}
                            <div style="border: 1px solid #ddd; border-radius: 6px; padding: 12px; margin-bottom: 12px; background: #fafafa;">
                                <p><strong>🔹 行动：</strong>{{ step.action }}</p>
                                {% if step.timing_or_condition %}
                                <p><strong>🕒 时机/条件：</strong>{{ step.timing_or_condition }}</p>
                                {% endif %}
                                {% if step.required_resource %}
                                <p><strong>📦 所需资源：</strong>{{ step.required_resource }}</p>
                                {% endif %}
                                {% if step.potential_risk %}
                                <p><strong>⚠️ 潜在风险：</strong>{{ step.potential_risk }}</p>
                                {% endif %}
                                {% if step.contingency_response %}
                                <p><strong>🛡️ 应对措施：</strong>{{ step.contingency_response }}</p>
                                {% endif %}
                            </div>
                            {% endfor %}
                        </div>
                        {% endif %}

                        <!-- 回退计划（结构化） -->
                        {% if data.rational_advice.get('fallback_plan') %}
                        <h4 style="margin-top: 16px; color: #8e44ad;">🛡️ 回退计划（高风险触发时的最小安全措施）</h4>
                        <div class="advice-list" style="background: #f9f0ff; padding: 10px; border-left: 3px solid #9b59b6;">
                            {% for fp in data.rational_advice.fallback_plan %}
                            <div style="margin-bottom: 10px; padding: 8px; background: white; border-radius: 4px;">
                                <p><strong>🚨 触发条件：</strong>{{ fp.trigger_condition }}</p>
                                <p><strong>🔄 回退行动：</strong>{{ fp.fallback_action }}</p>
                            </div>
                            {% endfor %}
                        </div>
                        {% endif %}

                        <!-- 长期脱离路径 -->
                        {% if data.rational_advice.get('long_term_exit_path') %}
                        <h4 style="margin-top: 16px;">🚪 长期脱离路径（可持续退出）</h4>
                        <ul class="advice-list">
                            {% for item in data.rational_advice.long_term_exit_path %}
                            <li>{{ item }}</li>
                            {% endfor %}
                        </ul>
                        {% endif %}

                        <!-- 现有支持再诠释 -->
                        {% if data.rational_advice.get('available_social_support_reinterpretation') %}
                        <h4 style="margin-top: 16px;">🤝 现有支持的重新激活</h4>
                        <ul class="advice-list">
                            {% for item in data.rational_advice.available_social_support_reinterpretation %}
                            <li>{{ item }}</li>
                            {% endfor %}
                        </ul>
                        {% endif %}

                        <!-- 利益相关方代价评估 -->
                        {% if data.rational_advice.get('stakeholder_tradeoffs') %}
                        <details class="details-block" style="margin-top: 16px;">
                            <summary>⚖️ 利益相关方代价评估</summary>
                            <div style="margin-top: 8px; padding: 10px; background: #f8f9fa; border-radius: 6px; font-size: 0.95em;">
                                {% if data.rational_advice.stakeholder_tradeoffs.get('victim_cost') %}
                                <p><span class="field-label">低位者风险：</span>{{ data.rational_advice.stakeholder_tradeoffs.victim_cost | join('; ') }}</p>
                                {% endif %}
                                {% if data.rational_advice.stakeholder_tradeoffs.get('oppressor_loss') %}
                                <p><span class="field-label">高位者损失：</span>{{ data.rational_advice.stakeholder_tradeoffs.oppressor_loss | join('; ') }}</p>
                                {% endif %}
                                {% if data.rational_advice.stakeholder_tradeoffs.get('system_stability') %}
                                <p><span class="field-label">系统稳定性影响：</span>{{ data.rational_advice.stakeholder_tradeoffs.system_stability | join('; ') }}</p>
                                {% endif %}
                                {% if data.rational_advice.stakeholder_tradeoffs.get('evidence') %}
                                <p><span class="field-label">评估依据（语义标识）：</span>
                                    {% for frag in data.rational_advice.stakeholder_tradeoffs.evidence %}
                                    <code>{{ frag }}</code>{% if not loop.last %}, {% endif %}
                                    {% endfor %}
                                </p>
                                {% endif %}
                            </div>
                        </details>
                        {% endif %}

                    </div>
                </details>
            </div>
        </div>
        {% endif %}

        {% if data.analysis and data.analysis.suggestion %}
            <section class="suggestion-section">
                <h3>17. 用户输入内容解读</h3>
                {% if data.analysis.suggestion.success %}
                    <div class="suggestion-content">{{ data.analysis.suggestion.content }}</div>
                {% else %}
                    <div class="suggestion-error">
                      <em>{{ data.analysis.suggestion.content }}</em>
                    </div>
                {% endif %}
            </section>
        {% endif %}

        <!-- 若无任何数据 -->
        {% if not data or (data|length == 0) %}
        <p class="empty-section">暂无分析数据。</p>
        {% endif %}
    </div>

    <!-- 分享选项 -->
    <div class="share-options">
        <h3>分享这份报告：</h3>
        <button id="btn-export-md" class="share-btn" onclick="saveAsMarkdown()">
            💾 导出为 Markdown
        </button>
        <button id="btn-generate-pdf" class="share-btn" onclick="generatePDF()">
            🖨️ 生成PDF报告
        </button>
        <button id="btn-copy-text" class="share-btn" onclick="copyReportText()">
            📋 复制报告文本
        </button>
    </div>

    <!-- 图标 -->
    <div id="scroll-controls" style="
        position: fixed;
        bottom: 20px;
        right: 20px;
        display: flex;
        flex-direction: column;
        gap: 12px;
        z-index: 1000;
    ">
        <button onclick="window.scrollTo({top: 0, behavior: 'smooth'})"
                title="回到顶部"
                style="background: none; border: none; font-size: 24px; cursor: pointer; padding: 0; color: #666; transition: transform 0.3s ease, color 0.3s ease;"
                onmouseover="this.style.transform='scale(1.2)'; this.style.color='#000';"
                onmouseout="this.style.transform='scale(1)'; this.style.color='#666';">
            ▲
        </button>
        <button onclick="window.scrollTo({top: document.body.scrollHeight, behavior: 'smooth'})"
                title="滚动到底"
                style="background: none; border: none; font-size: 24px; cursor: pointer; padding: 0; color: #666; transition: transform 0.3s ease, color 0.3s ease;"
                onmouseover="this.style.transform='scale(1.2)'; this.style.color='#000';"
                onmouseout="this.style.transform='scale(1)'; this.style.color='#666';">
            ▼
        </button>
    </div>

    <script>
        var TurndownService = (function () {
          'use strict';

          function extend (destination) {
            for (var i = 1; i < arguments.length; i++) {
              var source = arguments[i];
              for (var key in source) {
                if (source.hasOwnProperty(key)) destination[key] = source[key];
              }
            }
            return destination
          }

          function repeat (character, count) {
            return Array(count + 1).join(character)
          }

          function trimLeadingNewlines (string) {
            return string.replace(/^\n*/, '')
          }

          function trimTrailingNewlines (string) {
            // avoid match-at-end regexp bottleneck, see #370
            var indexEnd = string.length;
            while (indexEnd > 0 && string[indexEnd - 1] === '\n') indexEnd--;
            return string.substring(0, indexEnd)
          }

          var blockElements = [
            'ADDRESS', 'ARTICLE', 'ASIDE', 'AUDIO', 'BLOCKQUOTE', 'BODY', 'CANVAS',
            'CENTER', 'DD', 'DIR', 'DIV', 'DL', 'DT', 'FIELDSET', 'FIGCAPTION', 'FIGURE',
            'FOOTER', 'FORM', 'FRAMESET', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'HEADER',
            'HGROUP', 'HR', 'HTML', 'ISINDEX', 'LI', 'MAIN', 'MENU', 'NAV', 'NOFRAMES',
            'NOSCRIPT', 'OL', 'OUTPUT', 'P', 'PRE', 'SECTION', 'TABLE', 'TBODY', 'TD',
            'TFOOT', 'TH', 'THEAD', 'TR', 'UL'
          ];

          function isBlock (node) {
            return is(node, blockElements)
          }

          var voidElements = [
            'AREA', 'BASE', 'BR', 'COL', 'COMMAND', 'EMBED', 'HR', 'IMG', 'INPUT',
            'KEYGEN', 'LINK', 'META', 'PARAM', 'SOURCE', 'TRACK', 'WBR'
          ];

          function isVoid (node) {
            return is(node, voidElements)
          }

          function hasVoid (node) {
            return has(node, voidElements)
          }

          var meaningfulWhenBlankElements = [
            'A', 'TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TH', 'TD', 'IFRAME', 'SCRIPT',
            'AUDIO', 'VIDEO'
          ];

          function isMeaningfulWhenBlank (node) {
            return is(node, meaningfulWhenBlankElements)
          }

          function hasMeaningfulWhenBlank (node) {
            return has(node, meaningfulWhenBlankElements)
          }

          function is (node, tagNames) {
            return tagNames.indexOf(node.nodeName) >= 0
          }

          function has (node, tagNames) {
            return (
              node.getElementsByTagName &&
              tagNames.some(function (tagName) {
                return node.getElementsByTagName(tagName).length
              })
            )
          }

          var rules = {};

          rules.paragraph = {
            filter: 'p',

            replacement: function (content) {
              return '\n\n' + content + '\n\n'
            }
          };

          rules.lineBreak = {
            filter: 'br',

            replacement: function (content, node, options) {
              return options.br + '\n'
            }
          };

          rules.heading = {
            filter: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],

            replacement: function (content, node, options) {
              var hLevel = Number(node.nodeName.charAt(1));

              if (options.headingStyle === 'setext' && hLevel < 3) {
                var underline = repeat((hLevel === 1 ? '=' : '-'), content.length);
                return (
                  '\n\n' + content + '\n' + underline + '\n\n'
                )
              } else {
                return '\n\n' + repeat('#', hLevel) + ' ' + content + '\n\n'
              }
            }
          };

          rules.blockquote = {
            filter: 'blockquote',

            replacement: function (content) {
              content = content.replace(/^\n+|\n+$/g, '');
              content = content.replace(/^/gm, '> ');
              return '\n\n' + content + '\n\n'
            }
          };

          rules.list = {
            filter: ['ul', 'ol'],

            replacement: function (content, node) {
              var parent = node.parentNode;
              if (parent.nodeName === 'LI' && parent.lastElementChild === node) {
                return '\n' + content
              } else {
                return '\n\n' + content + '\n\n'
              }
            }
          };

          rules.listItem = {
            filter: 'li',

            replacement: function (content, node, options) {
              content = content
                .replace(/^\n+/, '') // remove leading newlines
                .replace(/\n+$/, '\n') // replace trailing newlines with just a single one
                .replace(/\n/gm, '\n    '); // indent
              var prefix = options.bulletListMarker + '   ';
              var parent = node.parentNode;
              if (parent.nodeName === 'OL') {
                var start = parent.getAttribute('start');
                var index = Array.prototype.indexOf.call(parent.children, node);
                prefix = (start ? Number(start) + index : index + 1) + '.  ';
              }
              return (
                prefix + content + (node.nextSibling && !/\n$/.test(content) ? '\n' : '')
              )
            }
          };

          rules.indentedCodeBlock = {
            filter: function (node, options) {
              return (
                options.codeBlockStyle === 'indented' &&
                node.nodeName === 'PRE' &&
                node.firstChild &&
                node.firstChild.nodeName === 'CODE'
              )
            },

            replacement: function (content, node, options) {
              return (
                '\n\n    ' +
                node.firstChild.textContent.replace(/\n/g, '\n    ') +
                '\n\n'
              )
            }
          };

          rules.fencedCodeBlock = {
            filter: function (node, options) {
              return (
                options.codeBlockStyle === 'fenced' &&
                node.nodeName === 'PRE' &&
                node.firstChild &&
                node.firstChild.nodeName === 'CODE'
              )
            },

            replacement: function (content, node, options) {
              var className = node.firstChild.getAttribute('class') || '';
              var language = (className.match(/language-(\S+)/) || [null, ''])[1];
              var code = node.firstChild.textContent;

              var fenceChar = options.fence.charAt(0);
              var fenceSize = 3;
              var fenceInCodeRegex = new RegExp('^' + fenceChar + '{3,}', 'gm');

              var match;
              while ((match = fenceInCodeRegex.exec(code))) {
                if (match[0].length >= fenceSize) {
                  fenceSize = match[0].length + 1;
                }
              }

              var fence = repeat(fenceChar, fenceSize);

              return (
                '\n\n' + fence + language + '\n' +
                code.replace(/\n$/, '') +
                '\n' + fence + '\n\n'
              )
            }
          };

          rules.horizontalRule = {
            filter: 'hr',

            replacement: function (content, node, options) {
              return '\n\n' + options.hr + '\n\n'
            }
          };

          rules.inlineLink = {
            filter: function (node, options) {
              return (
                options.linkStyle === 'inlined' &&
                node.nodeName === 'A' &&
                node.getAttribute('href')
              )
            },

            replacement: function (content, node) {
              var href = node.getAttribute('href');
              var title = cleanAttribute(node.getAttribute('title'));
              if (title) title = ' "' + title + '"';
              return '[' + content + '](' + href + title + ')'
            }
          };

          rules.referenceLink = {
            filter: function (node, options) {
              return (
                options.linkStyle === 'referenced' &&
                node.nodeName === 'A' &&
                node.getAttribute('href')
              )
            },

            replacement: function (content, node, options) {
              var href = node.getAttribute('href');
              var title = cleanAttribute(node.getAttribute('title'));
              if (title) title = ' "' + title + '"';
              var replacement;
              var reference;

              switch (options.linkReferenceStyle) {
                case 'collapsed':
                  replacement = '[' + content + '][]';
                  reference = '[' + content + ']: ' + href + title;
                  break
                case 'shortcut':
                  replacement = '[' + content + ']';
                  reference = '[' + content + ']: ' + href + title;
                  break
                default:
                  var id = this.references.length + 1;
                  replacement = '[' + content + '][' + id + ']';
                  reference = '[' + id + ']: ' + href + title;
              }

              this.references.push(reference);
              return replacement
            },

            references: [],

            append: function (options) {
              var references = '';
              if (this.references.length) {
                references = '\n\n' + this.references.join('\n') + '\n\n';
                this.references = []; // Reset references
              }
              return references
            }
          };

          rules.emphasis = {
            filter: ['em', 'i'],

            replacement: function (content, node, options) {
              if (!content.trim()) return ''
              return options.emDelimiter + content + options.emDelimiter
            }
          };

          rules.strong = {
            filter: ['strong', 'b'],

            replacement: function (content, node, options) {
              if (!content.trim()) return ''
              return options.strongDelimiter + content + options.strongDelimiter
            }
          };

          rules.code = {
            filter: function (node) {
              var hasSiblings = node.previousSibling || node.nextSibling;
              var isCodeBlock = node.parentNode.nodeName === 'PRE' && !hasSiblings;

              return node.nodeName === 'CODE' && !isCodeBlock
            },

            replacement: function (content) {
              if (!content) return ''
              content = content.replace(/\r?\n|\r/g, ' ');

              var extraSpace = /^`|^ .*?[^ ].* $|`$/.test(content) ? ' ' : '';
              var delimiter = '`';
              var matches = content.match(/`+/gm) || [];
              while (matches.indexOf(delimiter) !== -1) delimiter = delimiter + '`';

              return delimiter + extraSpace + content + extraSpace + delimiter
            }
          };

          rules.image = {
            filter: 'img',

            replacement: function (content, node) {
              var alt = cleanAttribute(node.getAttribute('alt'));
              var src = node.getAttribute('src') || '';
              var title = cleanAttribute(node.getAttribute('title'));
              var titlePart = title ? ' "' + title + '"' : '';
              return src ? '![' + alt + ']' + '(' + src + titlePart + ')' : ''
            }
          };

          function cleanAttribute (attribute) {
            return attribute ? attribute.replace(/(\n+\s*)+/g, '\n') : ''
          }

          /**
           * Manages a collection of rules used to convert HTML to Markdown
           */

          function Rules (options) {
            this.options = options;
            this._keep = [];
            this._remove = [];

            this.blankRule = {
              replacement: options.blankReplacement
            };

            this.keepReplacement = options.keepReplacement;

            this.defaultRule = {
              replacement: options.defaultReplacement
            };

            this.array = [];
            for (var key in options.rules) this.array.push(options.rules[key]);
          }

          Rules.prototype = {
            add: function (key, rule) {
              this.array.unshift(rule);
            },

            keep: function (filter) {
              this._keep.unshift({
                filter: filter,
                replacement: this.keepReplacement
              });
            },

            remove: function (filter) {
              this._remove.unshift({
                filter: filter,
                replacement: function () {
                  return ''
                }
              });
            },

            forNode: function (node) {
              if (node.isBlank) return this.blankRule
              var rule;

              if ((rule = findRule(this.array, node, this.options))) return rule
              if ((rule = findRule(this._keep, node, this.options))) return rule
              if ((rule = findRule(this._remove, node, this.options))) return rule

              return this.defaultRule
            },

            forEach: function (fn) {
              for (var i = 0; i < this.array.length; i++) fn(this.array[i], i);
            }
          };

          function findRule (rules, node, options) {
            for (var i = 0; i < rules.length; i++) {
              var rule = rules[i];
              if (filterValue(rule, node, options)) return rule
            }
            return void 0
          }

          function filterValue (rule, node, options) {
            var filter = rule.filter;
            if (typeof filter === 'string') {
              if (filter === node.nodeName.toLowerCase()) return true
            } else if (Array.isArray(filter)) {
              if (filter.indexOf(node.nodeName.toLowerCase()) > -1) return true
            } else if (typeof filter === 'function') {
              if (filter.call(rule, node, options)) return true
            } else {
              throw new TypeError('`filter` needs to be a string, array, or function')
            }
          }

          /**
           * The collapseWhitespace function is adapted from collapse-whitespace
           * by Luc Thevenard.
           *
           * The MIT License (MIT)
           *
           * Copyright (c) 2014 Luc Thevenard <lucthevenard@gmail.com>
           *
           * Permission is hereby granted, free of charge, to any person obtaining a copy
           * of this software and associated documentation files (the "Software"), to deal
           * in the Software without restriction, including without limitation the rights
           * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
           * copies of the Software, and to permit persons to whom the Software is
           * furnished to do so, subject to the following conditions:
           *
           * The above copyright notice and this permission notice shall be included in
           * all copies or substantial portions of the Software.
           *
           * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
           * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
           * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
           * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
           * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
           * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
           * THE SOFTWARE.
           */

          /**
           * collapseWhitespace(options) removes extraneous whitespace from an the given element.
           *
           * @param {Object} options
           */
          function collapseWhitespace (options) {
            var element = options.element;
            var isBlock = options.isBlock;
            var isVoid = options.isVoid;
            var isPre = options.isPre || function (node) {
              return node.nodeName === 'PRE'
            };

            if (!element.firstChild || isPre(element)) return

            var prevText = null;
            var keepLeadingWs = false;

            var prev = null;
            var node = next(prev, element, isPre);

            while (node !== element) {
              if (node.nodeType === 3 || node.nodeType === 4) { // Node.TEXT_NODE or Node.CDATA_SECTION_NODE
                var text = node.data.replace(/[ \r\n\t]+/g, ' ');

                if ((!prevText || / $/.test(prevText.data)) &&
                    !keepLeadingWs && text[0] === ' ') {
                  text = text.substr(1);
                }

                // `text` might be empty at this point.
                if (!text) {
                  node = remove(node);
                  continue
                }

                node.data = text;

                prevText = node;
              } else if (node.nodeType === 1) { // Node.ELEMENT_NODE
                if (isBlock(node) || node.nodeName === 'BR') {
                  if (prevText) {
                    prevText.data = prevText.data.replace(/ $/, '');
                  }

                  prevText = null;
                  keepLeadingWs = false;
                } else if (isVoid(node) || isPre(node)) {
                  // Avoid trimming space around non-block, non-BR void elements and inline PRE.
                  prevText = null;
                  keepLeadingWs = true;
                } else if (prevText) {
                  // Drop protection if set previously.
                  keepLeadingWs = false;
                }
              } else {
                node = remove(node);
                continue
              }

              var nextNode = next(prev, node, isPre);
              prev = node;
              node = nextNode;
            }

            if (prevText) {
              prevText.data = prevText.data.replace(/ $/, '');
              if (!prevText.data) {
                remove(prevText);
              }
            }
          }

          /**
           * remove(node) removes the given node from the DOM and returns the
           * next node in the sequence.
           *
           * @param {Node} node
           * @return {Node} node
           */
          function remove (node) {
            var next = node.nextSibling || node.parentNode;

            node.parentNode.removeChild(node);

            return next
          }

          /**
           * next(prev, current, isPre) returns the next node in the sequence, given the
           * current and previous nodes.
           *
           * @param {Node} prev
           * @param {Node} current
           * @param {Function} isPre
           * @return {Node}
           */
          function next (prev, current, isPre) {
            if ((prev && prev.parentNode === current) || isPre(current)) {
              return current.nextSibling || current.parentNode
            }

            return current.firstChild || current.nextSibling || current.parentNode
          }

          /*
           * Set up window for Node.js
           */

          var root = (typeof window !== 'undefined' ? window : {});

          /*
           * Parsing HTML strings
           */

          function canParseHTMLNatively () {
            var Parser = root.DOMParser;
            var canParse = false;

            // Adapted from https://gist.github.com/1129031
            // Firefox/Opera/IE throw errors on unsupported types
            try {
              // WebKit returns null on unsupported types
              if (new Parser().parseFromString('', 'text/html')) {
                canParse = true;
              }
            } catch (e) {}

            return canParse
          }

          function createHTMLParser () {
            var Parser = function () {};

            {
              if (shouldUseActiveX()) {
                Parser.prototype.parseFromString = function (string) {
                  var doc = new window.ActiveXObject('htmlfile');
                  doc.designMode = 'on'; // disable on-page scripts
                  doc.open();
                  doc.write(string);
                  doc.close();
                  return doc
                };
              } else {
                Parser.prototype.parseFromString = function (string) {
                  var doc = document.implementation.createHTMLDocument('');
                  doc.open();
                  doc.write(string);
                  doc.close();
                  return doc
                };
              }
            }
            return Parser
          }

          function shouldUseActiveX () {
            var useActiveX = false;
            try {
              document.implementation.createHTMLDocument('').open();
            } catch (e) {
              if (window.ActiveXObject) useActiveX = true;
            }
            return useActiveX
          }

          var HTMLParser = canParseHTMLNatively() ? root.DOMParser : createHTMLParser();

          function RootNode (input, options) {
            var root;
            if (typeof input === 'string') {
              var doc = htmlParser().parseFromString(
                // DOM parsers arrange elements in the <head> and <body>.
                // Wrapping in a custom element ensures elements are reliably arranged in
                // a single element.
                '<x-turndown id="turndown-root">' + input + '</x-turndown>',
                'text/html'
              );
              root = doc.getElementById('turndown-root');
            } else {
              root = input.cloneNode(true);
            }
            collapseWhitespace({
              element: root,
              isBlock: isBlock,
              isVoid: isVoid,
              isPre: options.preformattedCode ? isPreOrCode : null
            });

            return root
          }

          var _htmlParser;
          function htmlParser () {
            _htmlParser = _htmlParser || new HTMLParser();
            return _htmlParser
          }

          function isPreOrCode (node) {
            return node.nodeName === 'PRE' || node.nodeName === 'CODE'
          }

          function Node (node, options) {
            node.isBlock = isBlock(node);
            node.isCode = node.nodeName === 'CODE' || node.parentNode.isCode;
            node.isBlank = isBlank(node);
            node.flankingWhitespace = flankingWhitespace(node, options);
            return node
          }

          function isBlank (node) {
            return (
              !isVoid(node) &&
              !isMeaningfulWhenBlank(node) &&
              /^\s*$/i.test(node.textContent) &&
              !hasVoid(node) &&
              !hasMeaningfulWhenBlank(node)
            )
          }

          function flankingWhitespace (node, options) {
            if (node.isBlock || (options.preformattedCode && node.isCode)) {
              return { leading: '', trailing: '' }
            }

            var edges = edgeWhitespace(node.textContent);

            // abandon leading ASCII WS if left-flanked by ASCII WS
            if (edges.leadingAscii && isFlankedByWhitespace('left', node, options)) {
              edges.leading = edges.leadingNonAscii;
            }

            // abandon trailing ASCII WS if right-flanked by ASCII WS
            if (edges.trailingAscii && isFlankedByWhitespace('right', node, options)) {
              edges.trailing = edges.trailingNonAscii;
            }

            return { leading: edges.leading, trailing: edges.trailing }
          }

          function edgeWhitespace (string) {
            var m = string.match(/^(([ \t\r\n]*)(\s*))(?:(?=\S)[\s\S]*\S)?((\s*?)([ \t\r\n]*))$/);
            return {
              leading: m[1], // whole string for whitespace-only strings
              leadingAscii: m[2],
              leadingNonAscii: m[3],
              trailing: m[4], // empty for whitespace-only strings
              trailingNonAscii: m[5],
              trailingAscii: m[6]
            }
          }

          function isFlankedByWhitespace (side, node, options) {
            var sibling;
            var regExp;
            var isFlanked;

            if (side === 'left') {
              sibling = node.previousSibling;
              regExp = / $/;
            } else {
              sibling = node.nextSibling;
              regExp = /^ /;
            }

            if (sibling) {
              if (sibling.nodeType === 3) {
                isFlanked = regExp.test(sibling.nodeValue);
              } else if (options.preformattedCode && sibling.nodeName === 'CODE') {
                isFlanked = false;
              } else if (sibling.nodeType === 1 && !isBlock(sibling)) {
                isFlanked = regExp.test(sibling.textContent);
              }
            }
            return isFlanked
          }

          var reduce = Array.prototype.reduce;
          var escapes = [
            [/\\/g, '\\\\'],
            [/\*/g, '\\*'],
            [/^-/g, '\\-'],
            [/^\+ /g, '\\+ '],
            [/^(=+)/g, '\\$1'],
            [/^(#{1,6}) /g, '\\$1 '],
            [/`/g, '\\`'],
            [/^~~~/g, '\\~~~'],
            [/\[/g, '\\['],
            [/\]/g, '\\]'],
            [/^>/g, '\\>'],
            [/_/g, '\\_'],
            [/^(\d+)\. /g, '$1\\. ']
          ];

          function TurndownService (options) {
            if (!(this instanceof TurndownService)) return new TurndownService(options)

            var defaults = {
              rules: rules,
              headingStyle: 'setext',
              hr: '* * *',
              bulletListMarker: '*',
              codeBlockStyle: 'indented',
              fence: '```',
              emDelimiter: '_',
              strongDelimiter: '**',
              linkStyle: 'inlined',
              linkReferenceStyle: 'full',
              br: '  ',
              preformattedCode: false,
              blankReplacement: function (content, node) {
                return node.isBlock ? '\n\n' : ''
              },
              keepReplacement: function (content, node) {
                return node.isBlock ? '\n\n' + node.outerHTML + '\n\n' : node.outerHTML
              },
              defaultReplacement: function (content, node) {
                return node.isBlock ? '\n\n' + content + '\n\n' : content
              }
            };
            this.options = extend({}, defaults, options);
            this.rules = new Rules(this.options);
          }

          TurndownService.prototype = {
            /**
             * The entry point for converting a string or DOM node to Markdown
             * @public
             * @param {String|HTMLElement} input The string or DOM node to convert
             * @returns A Markdown representation of the input
             * @type String
             */

            turndown: function (input) {
              if (!canConvert(input)) {
                throw new TypeError(
                  input + ' is not a string, or an element/document/fragment node.'
                )
              }

              if (input === '') return ''

              var output = process.call(this, new RootNode(input, this.options));
              return postProcess.call(this, output)
            },

            /**
             * Add one or more plugins
             * @public
             * @param {Function|Array} plugin The plugin or array of plugins to add
             * @returns The Turndown instance for chaining
             * @type Object
             */

            use: function (plugin) {
              if (Array.isArray(plugin)) {
                for (var i = 0; i < plugin.length; i++) this.use(plugin[i]);
              } else if (typeof plugin === 'function') {
                plugin(this);
              } else {
                throw new TypeError('plugin must be a Function or an Array of Functions')
              }
              return this
            },

            /**
             * Adds a rule
             * @public
             * @param {String} key The unique key of the rule
             * @param {Object} rule The rule
             * @returns The Turndown instance for chaining
             * @type Object
             */

            addRule: function (key, rule) {
              this.rules.add(key, rule);
              return this
            },

            /**
             * Keep a node (as HTML) that matches the filter
             * @public
             * @param {String|Array|Function} filter The unique key of the rule
             * @returns The Turndown instance for chaining
             * @type Object
             */

            keep: function (filter) {
              this.rules.keep(filter);
              return this
            },

            /**
             * Remove a node that matches the filter
             * @public
             * @param {String|Array|Function} filter The unique key of the rule
             * @returns The Turndown instance for chaining
             * @type Object
             */

            remove: function (filter) {
              this.rules.remove(filter);
              return this
            },

            /**
             * Escapes Markdown syntax
             * @public
             * @param {String} string The string to escape
             * @returns A string with Markdown syntax escaped
             * @type String
             */

            escape: function (string) {
              return escapes.reduce(function (accumulator, escape) {
                return accumulator.replace(escape[0], escape[1])
              }, string)
            }
          };

          /**
           * Reduces a DOM node down to its Markdown string equivalent
           * @private
           * @param {HTMLElement} parentNode The node to convert
           * @returns A Markdown representation of the node
           * @type String
           */

          function process (parentNode) {
            var self = this;
            return reduce.call(parentNode.childNodes, function (output, node) {
              node = new Node(node, self.options);

              var replacement = '';
              if (node.nodeType === 3) {
                replacement = node.isCode ? node.nodeValue : self.escape(node.nodeValue);
              } else if (node.nodeType === 1) {
                replacement = replacementForNode.call(self, node);
              }

              return join(output, replacement)
            }, '')
          }

          /**
           * Appends strings as each rule requires and trims the output
           * @private
           * @param {String} output The conversion output
           * @returns A trimmed version of the ouput
           * @type String
           */

          function postProcess (output) {
            var self = this;
            this.rules.forEach(function (rule) {
              if (typeof rule.append === 'function') {
                output = join(output, rule.append(self.options));
              }
            });

            return output.replace(/^[\t\r\n]+/, '').replace(/[\t\r\n\s]+$/, '')
          }

          /**
           * Converts an element node to its Markdown equivalent
           * @private
           * @param {HTMLElement} node The node to convert
           * @returns A Markdown representation of the node
           * @type String
           */

          function replacementForNode (node) {
            var rule = this.rules.forNode(node);
            var content = process.call(this, node);
            var whitespace = node.flankingWhitespace;
            if (whitespace.leading || whitespace.trailing) content = content.trim();
            return (
              whitespace.leading +
              rule.replacement(content, node, this.options) +
              whitespace.trailing
            )
          }

          /**
           * Joins replacement to the current output with appropriate number of new lines
           * @private
           * @param {String} output The current conversion output
           * @param {String} replacement The string to append to the output
           * @returns Joined output
           * @type String
           */

          function join (output, replacement) {
            var s1 = trimTrailingNewlines(output);
            var s2 = trimLeadingNewlines(replacement);
            var nls = Math.max(output.length - s1.length, replacement.length - s2.length);
            var separator = '\n\n'.substring(0, nls);

            return s1 + separator + s2
          }

          /**
           * Determines whether an input can be converted
           * @private
           * @param {String|HTMLElement} input Describe this parameter
           * @returns Describe what it returns
           * @type String|Object|Array|Boolean|Number
           */

          function canConvert (input) {
            return (
              input != null && (
                typeof input === 'string' ||
                (input.nodeType && (
                  input.nodeType === 1 || input.nodeType === 9 || input.nodeType === 11
                ))
              )
            )
          }

          return TurndownService;

        }());
    </script>

    <script>
        const REPORT_TITLE = {{ data.meta.title | default('文本多模态感知分析报告') | tojson }}

        function saveAsMarkdown() {
            if (typeof TurndownService !== 'function') {
                alert('❌ Markdown 转换器未加载，请刷新页面。');
                return;
            }

            const reportEl = document.querySelector('.report');
            if (!reportEl) {
                alert('❌ 未找到 .report 元素');
                return;
            }

            // 克隆并清理
            const clone = reportEl.cloneNode(true);
            clone.querySelectorAll('script, style, .no-export').forEach(el => el.remove());

            // 转换
            const turndownService = new TurndownService({
                headingStyle: 'atx',
                bulletListMarker: '-',
                codeBlockStyle: 'fenced'
            });
            let markdown = turndownService.turndown(clone.innerHTML);

            // 清理多余空行
            markdown = markdown.replace(/\n{3,}/g, '\n\n').trim();

            // 生成安全文件名
            const safeName = REPORT_TITLE
                .replace(/[<>:"/\\|?*\x00-\x1F]/g, '_')
                .replace(/\s+/g, '_')
                .substring(0, 60) || 'report';

            // 下载
            const blob = new Blob([markdown], { type: 'text/markdown;charset=utf-8' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = `${safeName}.md`;
            a.style.display = 'none';
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        }

        function copyReportText() {
            const el = document.querySelector('.report');
            if (!el) {
                alert('❌ 未找到报告内容。');
                return;
            }
            const text = el.innerText;
            if (navigator.clipboard) {
                navigator.clipboard.writeText(text).then(() => {
                    alert('✅ 报告内容已复制到剪贴板！');
                }).catch(() => {
                    fallbackCopy(text);
                });
            } else {
                fallbackCopy(text);
            }
        }

        function fallbackCopy(text) {
            const textarea = document.createElement('textarea');
            textarea.value = text;
            textarea.style.position = 'fixed';
            textarea.style.opacity = '0';
            document.body.appendChild(textarea);
            textarea.select();
            try {
                document.execCommand('copy');
                alert('✅ 报告内容已复制（使用备用方案）！');
            } catch (err) {
                alert('❌ 请手动复制文本。');
            }
            document.body.removeChild(textarea);
        }

        function generatePDF() {
            window.print(); // 触发打印，用户可选择“另存为PDF”
        }
    </script>
</body>
</html>